소스 스크립트에서 네임스페이스 충돌/오염을 방지하는 방법은 무엇입니까?

소스 스크립트에서 네임스페이스 충돌/오염을 방지하는 방법은 무엇입니까?

foo.sh궁극적으로 명령을 실행하는 스크립트 bar(일부 매개변수 사용) 를 구현하고 싶습니다 . 이 명령은 bar현재 쉘 환경을 수정합니다. 즉, 1foo.sh 에서 시작되어야 합니다 . (그런데 구현은 완전히 내 통제 범위를 벗어났습니다.)bar

에서 대부분의 코드 목적은 foo.sh에 전달될 매개변수를 계산하는 것입니다 bar.

합리적인 가독성/유지보수성을 유지하기 위해 foo.sh많은 보조 변수를 정의해야 한다는 것을 알게 되었습니다. 불행하게도 이것은

  1. 네임스페이스 충돌(예: 기존 매개변수 삭제)
  2. 네임스페이스 오염(예: 중복 매개변수로 환경을 복잡하게 함)

이러한 문제를 피하거나 최소한 완화할 수 있는 한 가지 가능한 방법은 호출 범위에 포함될 적절한 코드 문자열을 foo.sh에코하는 함수(모든 변수가 선언된 상태)에 대부분의 코드를 넣는 것입니다 .localeval

{
  __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

관련 정보