긴 옵션 만있는 bash 명령 줄에서 getopt를 사용하는 방법은 무엇입니까?

bash 명령 줄에 getopt 명령이 있습니다. getopt는 짧은 옵션 (예 : getopt -o axby "$@")과 함께 사용할 수 있으며 짧은 옵션과 긴 옵션 (예 : getopt -o axby -l long-key -- "$@"), 그러나 이제는 긴 옵션 만 필요합니다 (즉, 짧은 옵션은 전혀 존재하지 않음). 그러나 명령은 getopt -l long-key -- "$@"--long-key 옵션을 올바르게 구문 분석하지 않습니다. 그렇다면 긴 옵션 과 함께 getopt 명령을 어떻게 사용할 수 있습니까? 아니면 불가능하거나 단지 getopt 명령의 버그입니까?

댓글

  • 당신 내부 getopts에 대한 태그이지만 /usr/bin/getopt 명령을 사용하고 있습니다.
  • @Anthon 죄송합니다. 잘못된 태그이지만 ' 다른 태그를 추가 할만큼 평판이 충분하지 않아 300 개의 평판이 필요합니다. 하지만 방금 잘못된 태그를 삭제했습니다.

답변

getopt는 짧은 옵션이 없어도 완벽합니다. 그러나 당신은 짧은 선택권이 없다고 말할 필요가 있습니다. 설명서의 구문에서 “특이합니다.

-o 또는 --options 옵션은 첫 번째 부분에 있으며 두 번째 부분의 첫 번째 매개 변수는 짧은 옵션 문자열로 사용됩니다.

이것이 바로 테스트에서 일어나는 일입니다. getopt -l long-key -- --long-key foo--long-key를 옵션 목록으로 취급합니다. -egklnoyfoo를 유일한 인수로 사용합니다.

getopt -o "" -l long-key -- "$@" 

$ getopt -l long-key -o "" -- --long-key foo --long-key -- "foo" $ getopt -l long-key -o "" -- --long-key --not-recognized -n foo getopt: unrecognized option "--not-recognized" getopt: invalid option -- "n" --long-key -- "foo" 

댓글

  • OP '가 및 getopt가 답변에 감염 되었습니까? getopts 주석으로 시작한 다음 .
  • @Anthon 모든 대답은 GNU coreutils의 getopt 프로그램에 대한 것입니다. I getopts라는 텍스트를 수정했습니다. 감사. getopts는 ' 긴 옵션도 수행하지 않으므로 getopts에는 적용되지 않습니다. .
  • OP에는 원래 getopts 태그가있었습니다. 나는 당신의 대답을 바꾸고 싶지 않았습니다. 당신은 당신이 쓰는 것에 대해 저보다 일반적으로 훨씬 더 잘 알고 있기 때문입니다. 🙂
  • 나는 이것을 알아 내려고 거의 한 시간을 잃었습니다. 헛된 커피 모금 몇 모금을 구해 주셨습니다. 감사합니다 … 이제이 커피를 더 잘 사용하도록하겠습니다. ☕️

답변

Dunno about getopt 그러나 getopts 내장 기능은 다음과 같은 긴 옵션 만 처리하는 데 사용할 수 있습니다.

while getopts :-: o do case "$o$OPTARG" in (-longopt1) process ;; (-longopt2) process ;; esac; done 

물론있는 그대로입니다. ” 긴 옵션이 논쟁을해야하는 경우에는 작동합니다. 그래도 할 수 있지만, 제가이 작업에 대해 배웠 듯이. 처음에 여기에 포함 시켰지만 긴 옵션의 경우별로 유용하지 않다는 것을 깨달았습니다.이 경우에는 case (match) 필드를 예측 가능한 단일 문자로 표시합니다. 이제 제가 아는 것은 짧은 옵션에 탁월하다는 것입니다. 길이를 알 수없는 문자열을 반복하고 옵션 문자열에 따라 단일 바이트를 선택할 때 가장 유용합니다. .하지만 옵션이 인자 인 경우 for var do case $var in 조합으로 할 수있는 작업이 많지 않습니다. 더 좋습니다. 단순하게 유지하기 위해.

getopt도 마찬가지라고 생각하지만 확실하게 말할 수있을만큼 충분히 알지 못합니다. 다음과 같은 arg 배열이 주어지면 나는 내 자신의 작은 arg 파서를 보여줄 것이다. 이것은 주로 내가 alias와 .

set -- this is ignored by default --lopt1 -s "some "\"" args" here --ignored and these are ignored \ --alsoignored andthis --lopt2 "and some "`more" --lopt1 and just a few more 

이것이 제가 작업 할 arg 문자열입니다. 지금 :

aopts() { env - sh -s -- "$@" } <<OPTCASE 3<<\OPTSCRIPT acase() case "\$a" in $(fmt=" (%s) f=%s; aset "?$(($f)):";;\n" for a do case "$a" in (--) break;; (--*[!_[:alnum:]]*) continue;; (--*) printf "$fmt" "$a" "${a#--}";; esac;done;printf "$fmt" "--*" ignored) (*) aset "" "\$a";;esac shift "$((SHIFT$$))"; f=ignored; exec <&3 OPTCASE aset() { alias "$f=$(($f${1:-=$(($f))+}1))" [ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; } for a do acase; done; alias #END OPTSCRIPT 

이는 -- 구분 기호로 구분 된 하나 또는 두 개의 인수 세트를 전달하는지 여부에 따라 두 가지 다른 방법 중 하나로 arg 배열을 처리합니다. 두 경우 모두 arg 배열에 대한 처리 순서에 적용됩니다.

다음과 같이 호출하는 경우 :

: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@" 

비즈니스는 acase() 함수를 다음과 같이 작성하는 것입니다.

acase() case "$a" in (--lopt1) f=lopt1; aset "?$(($f)):";; (--lopt2) f=lopt2; aset "?$(($f)):";; (--*) f=ignored; aset "?$(($f)):";; (*) aset "" "$a";;esac 

그리고 .acase() 함수 정의의 명령 대체는 호출 셸이 여기 문서에서 함수의 입력을 빌드 할 때 평가되지만 acase()는 물론 호출 쉘에서 호출되거나 정의되지 않았습니다. 물론 서브 쉘에서 호출되므로 명령 줄에서 원하는 옵션을 동적으로 지정할 수 있습니다.

구분되지 않은 배열은 문자열 --로 시작하는 모든 인수에 대한 일치 항목으로 acase()를 채 웁니다.

함수 서브 쉘에서 거의 모든 처리를 수행합니다. 각 arg의 값을 연관 이름으로 할당 된 별칭에 반복적으로 저장합니다. 완료되면 alias로 저장된 모든 값을 인쇄합니다.이 값은 셸에 다시 입력 할 수있는 방식으로 인용 된 모든 저장된 값을 인쇄하도록 POSIX 지정됩니다. 그래서 내가 할 때 …

aopts --lopt1 --lopt2 -- "$@" 

출력은 다음과 같습니다 :

...ignored... lopt1="8" lopt1_1="-s" lopt1_2="some "\"" args" lopt1_3="here" lopt1_4="and" lopt1_5="just" lopt1_6="a" lopt1_7="few" lopt1_8="more" lopt2="1" lopt2_1="and some "`more" 

인수 목록을 살펴볼 때 케이스 블록과 일치하는지 확인합니다. 일치하는 항목을 찾으면 f=optname 플래그를 던집니다. 다시 한 번 유효한 옵션을 찾을 때까지 현재 플래그를 기반으로 빌드하는 배열에 각 후속 인수를 추가합니다. 동일한 옵션이 여러 번 지정되면 결과가 복합되고 대체되지 않습니다. 대소 문자가 아닌 모든 항목 또는 무시 된 옵션 다음에 오는 인수는 무시 된 배열에 할당됩니다.

출력은 쉘에 의해 자동으로 쉘 입력에 대해 쉘로부터 보호됩니다. :

eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")" 

… 완벽하게 안전해야합니다. 어떤 이유로 든 안전하지 않다면 셸 관리자에게 버그 보고서를 제출해야합니다.

각 일치에 대해 두 종류의 별칭 값을 할당합니다. 첫째, 플래그를 설정합니다. 이것은 옵션이 일치하지 않는 인수 앞에 오는지 여부에 관계없이 발생합니다. 따라서 인수 목록에서 --flag가 발생하면 flag=1가 트리거됩니다. 이것은 복합적이지 않습니다. --flag --flag --flagflag=1 만 가져옵니다. 이 값은 뒤에 올 수있는 모든 인수에 대해 증가하지만 합니다 . 인덱스 키로 사용할 수 있습니다. 위의 eval를 수행 한 후 다음을 수행 할 수 있습니다.

printf %s\\n "$lopt1" "$lopt2" 

… to get …

8 1 

기타 :

for o in lopt1 lopt2 do list= i=0; echo "$o = $(($o))" while [ "$((i=$i+1))" -le "$(($o))" ] do list="$list $o $i \"\${${o}_$i}\" " done; eval "printf "%s[%02d] = %s\n" $list"; done 

출력

lopt1 = 8 lopt1[01] = -s lopt1[02] = some " args lopt1[03] = here lopt1[04] = and lopt1[05] = just lopt1[06] = a lopt1[07] = few lopt1[08] = more lopt2 = 1 lopt2[01] = and some "`more 

일치하지 않는 인수에 대해 위의 for ... in 필드에서 ignored 를 대체하여 다음을 얻습니다.

ignored = 10 ignored[01] = this ignored[02] = is ignored[03] = ignored ignored[04] = by ignored[05] = default ignored[06] = and ignored[07] = these ignored[08] = are ignored[09] = ignored ignored[10] = andthis 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다