매개변수를 구문 분석하기 위해 평가 세트 사용을 피하는 방법은 무엇입니까?

매개변수를 구문 분석하기 위해 평가 세트 사용을 피하는 방법은 무엇입니까?

매개변수 분석을 공부할 때세게 때리다스크립트 사용법선택 항목 가져오기, 나는 거의 모든 곳에서 이 구조가 사용되는 것을 보았습니다: eval set -- "$SOMETHING_PARSED". 예를 들어,여기그리고여기. 앞으로는 작업 스크립트를 무료로 공개할 예정이므로 사용자들에게 그런 공백을 남기고 싶지 않습니다. 이것을 피할 수 있는 방법이 있나요?

설명하다여기버전에 따라 다릅니다선택 항목 가져오기, 사용할 필요가 없습니다 eval. 하지만 적어도 내 경우는 그렇지 않다.선택 항목 가져오기다음과 같은 문자열이 주어지면 ' -j --version= '\''1'\'' --number= '\''2'\'' -- '\''2C_IA/GBCs_out/nohope_2C_IA_off. xml'\'''.& set는 이를 정확히 에 할당합니다 $1.

답변1

getopt비전통적인 방식으로 구현되거나 util-linux적어도 비전통적인 방식으로 사용되는 전체 요점 busybox은 평가할 쉘 코드를 출력한다는 것입니다. 쉘 구문의 특수 문자는 실제로 옵션 인수 1에서 인용되므로 getopt²를 제외하고 Bourne과 유사한 쉘에서 사용해도 안전합니다.yash

POSIX sh언어를 사용하면 명령이 임의의 문자열 목록을 셸에 반환하는 가장 간단한 방법입니다.

getopt이 작업 모드를 지원하지 않는 구현(예: getopt분할+글로브 연산자 사용에 의존한 원래 구현)은 임의 목록을 반환할 수 없기 때문에 의도적으로 손상되었습니다.

eval어떤 이유로든 사용하고 싶지 않지만 zsh전환할 수 있는 옵션이 있는 경우 다음을 사용할 수 있습니다.

argv=( "${(@XQ)${(z)$(getopt...)}}" ) || exit

매개 변수 확장 플래그는 쉘 인용 구문( 인용 구문이지만 작은 따옴표만 사용하여 인용) z을 기반으로 표시되며 , 따옴표를 제거하고 구문 오류가 발생하면 불평합니다.zshgetoptQX

유일한 이점은 getopt사악한 코드를 출력하는 사악한 명령으로 대체되면 실행되지 않는다는 것입니다.사악한 놈교체 중입니다 getopt. 가져가는 편이 나을 수도 있습니다.달리기평가할 수 있도록 출력하는 것이 아니라 사악한 코드 자체입니다.

NUL로 구분된 명령을 보내는 경우 출력을 배열로 읽어서 임의의 문자열 목록을 bash4.4+ 에 전달할 수 있습니다.sh

readarray -td '' array < <(cmd) || exit # readarray failed.
wait "$!" || exit # cmd failed
set -- "${array[@]}"

또는 다음과 같습니다 zsh:

argv=( "${(0@)$(cmd)}" ) || exit
argv[-1]=() # remove the empty trailing argument caused by the terminating NUL

getopt따라서 이론적으로 이 작동 모드를 사용하여 메서드를 구현하는 것이 가능합니다 .

getopt유틸리티는 출력을 평가할 것으로 예상되는 유일한 유틸리티는 아닙니다. 다음도 참조하세요.

eval "$(dbus-launch --sh-syntax)"
eval "$(dpkg-architecture -u)"
eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
eval "$(lesspipe)"
eval "$(xz --robot --version)"
eval "$(resize)"
eval "$(dircolors)"

쉘의 환경을 수정하는 데 사용됩니다.

현재 상태를 저장하고 나중에 복원하는 데 사용할 수 있는 모든 항목도 참조하세요.

aliases=$(alias -L) # zsh
aliases=$(alias -p) # ksh/bash
options=$(set +o)
locale=$(locale)

되돌리려 면 eval "$aliases"...eval "$options"

getopt사용된 구문 분석 옵션을 포함하지 않는 대안은 다음과 같습니다 eval.

  • 표준 getopts내장 기능( ksh93³ 제외)은 단일 문자 옵션만 지원합니다.
  • zshzparseopts큐브 의
  • 내 거getopts_longPOSIX sh함수

¹ 옵션 이름에는 없지만 적어도 버전 2.38에서는 버그로 간주될 수 있습니다. 스크립트 옵션에 어리석은 이름을 선택하지 않는 한 괜찮을 것입니다.

² 현재 버전 yash(2022년 6월 기준)은 유효한 텍스트만 처리할 수 있으므로 현재 로캘에서 텍스트로 디코딩할 수 없는 인수는 차단됩니다.

³ ksh93 getopts이나 zsh는 zparseoptsGNU(또는)와 같은 방식으로 옵션을 구문 분석하지 않습니다. 특히, 축약된 긴 옵션을 지원하지 않습니다.getopt_long()util-linux getopt

관련 정보