foo.sh
궁극적으로 명령을 실행하는 스크립트 bar
(일부 매개변수 사용) 를 구현하고 싶습니다 . 이 명령은 bar
현재 쉘 환경을 수정합니다. 즉, 1foo.sh
에서 시작되어야 합니다 . (그런데 구현은 완전히 내 통제 범위를 벗어났습니다.)bar
에서 대부분의 코드 목적은 foo.sh
에 전달될 매개변수를 계산하는 것입니다 bar
.
합리적인 가독성/유지보수성을 유지하기 위해 foo.sh
많은 보조 변수를 정의해야 한다는 것을 알게 되었습니다. 불행하게도 이것은
- 네임스페이스 충돌(예: 기존 매개변수 삭제)
- 네임스페이스 오염(예: 중복 매개변수로 환경을 복잡하게 함)
이러한 문제를 피하거나 최소한 완화할 수 있는 한 가지 가능한 방법은 호출 범위에 포함될 적절한 코드 문자열을 foo.sh
에코하는 함수(모든 변수가 선언된 상태)에 대부분의 코드를 넣는 것입니다 .local
eval
{
__messy_calculation () {
local x y z ...
local bar_arg_1 bar_arg_2 ...
...
echo "bar $bar_arg_1 bar_arg_2 ..."
}
eval "$( __messy_calculation )"
} always {
unfunction __messy_calculation
}
이는 네임스페이스 오염 문제를 해결하고 네임스페이스 충돌 문제를 함수 이름 문제로 줄입니다. (저는 eval을 사용하는 것을 별로 좋아하지 않습니다.)
내 생각에 이러한 상황은 이를 해결하기 위한 표준적인 방법이 이미 존재할 만큼 충분히 흔하다고 생각합니다. 그렇다면 알려주시기 바랍니다.
1bar
내 추론에 결함이 있는 경우 모든 코드(호출 포함)를 함수에 넣으면 명령줄에서 이 함수를 실행할 때 현재 환경이 영향을 받지 않아 함수가 쓸모 없게 된다는 점을 추가하겠습니다. . 대신 호출이 이루어진 행을 얻으면 bar
현재 환경이 예상대로 수정됩니다.
답변1
변수의 경우 위의 설명에서 언급한 대로 익명 함수를 사용할 수 있습니다. 이는 원하는 수의 변수를 정의할 수 있음을 의미합니다. 접두사가 붙은 발신자로부터 숨기려는 것 local
, 일반적으로 정의하는 발신자와 통신하려는 것:
function {
local my_var=foo
your_var=bar
: ...
}
하지만 함수의 경우 선언할 수 없기 때문에 작동하지 않습니다 local
. 나한테 이런 문제가 있어zshrcunfunction
그리고 내 "로컬" 함수의 모든 이름에 짧은 문자열 접두사를 추가하고(네임스페이스가 있는 C에서와 마찬가지로) 끝에 와일드카드를 추가하기로 결정했습니다.
function foo-do-something () {
: ...
}
function foo-do-some-more-stuff () {
: ...
}
function foo-main () {
local my_var=oof
you_var=rab
foo-do-something for bar
foo-do-some-more-stuff with baz
}
foo-main
unfunction -m 'foo-*'
제 생각에는 이것이 최선의 해결책은 아니지만(저는 로컬 기능을 선호합니다) 제게는 효과가 있습니다.
답변2
해결책은 하위 쉘, 중첩 함수 및 unset
기본 기능을 사용하는 것입니다.
my_app_main()
(
unset -f my_app_main
a()
(
x=1
echo "a.x is $x"
)
b()
(
x=2
echo "b.x is $x"
)
c()
(
echo "c.x is $x (empty)"
)
a
b
c
)
my_app_main "$@"
echo "$x (empty - x is gone)"
# all gone
type my_app_main a b c