긴 옵션만으로 bash 명령 줄에서 getopt를 사용하는 방법은 무엇입니까? 옵션 (예 getopt -o axby “$@”:)과 함께

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



답변

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'

답변

Dunno에 관한 getopt것이지만 getopts내장은 다음과 같은 긴 옵션 만 처리하는 데 사용할 수 있습니다.

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

물론 긴 옵션에 인수가 있어야하는 경우 작동하지 않습니다. 그러나이 작업을 배운 것처럼 할 수는 있습니다. 처음에 여기에 포함 시켰지만 긴 옵션의 경우 유틸리티가별로 없다는 것을 깨달았습니다. 이 경우 case (match)예측 가능한 단일 문자로 내 필드를 단축하는 것 입니다. 이제 내가 아는 것은 짧은 옵션에 우수하다는 것입니다. 알 수없는 길이의 문자열을 반복하고 옵션 문자열에 따라 단일 바이트를 선택할 때 가장 유용합니다. 그러나 옵션 arg 일 for var do case $var in때 할 수 있는 조합 으로 많은 일을 하지 않습니다. 간단하게 유지하는 것이 좋습니다.

나는 똑같은 것이 사실이라고 생각 getopt하지만 확실하게 말할 수는 없습니다. 나는에 대한 감사 왔어요 evalation / 할당 관계에 주로 의존 – 다음 인수 배열을 감안할 때, 나는 내 자신의 작은의 인수 파서 시연 alias$((shell=math)).

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

그것이 내가 작업 할 인수 문자열입니다. 지금:

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 배열의 처리 순서에 적용됩니다.

당신이 그것을 호출하면 :

: $((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

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

분리되지 않은 배열을 acase()전달하면 string으로 시작하는 모든 인수에 대한 일치 항목으로 채워집니다 --.

이 함수는 실질적으로 서브 쉘에서 모든 처리를 수행합니다. 각 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'

arg 목록을 살펴보면 case 블록과 일치하는지 확인합니다. 일치하는 것을 찾으면 플래그를 던집니다 f=optname. 유효한 옵션을 다시 찾을 때까지 각 후속 arg를 현재 플래그를 기반으로 빌드하는 배열에 추가합니다. 동일한 옵션이 여러 번 지정된 경우 결과가 복합적이고 무시되지 않습니다. 그렇지 않은 경우 또는 무시 된 옵션 뒤에 오는 인수는 무시 된 배열에 할당됩니다 .

출력은 쉘에 의해 자동으로 쉘 입력을 위해 쉘 안전합니다.

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

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

각 일치에 대해 두 가지 종류의 별명 값을 지정합니다. 먼저 플래그를 설정합니다. 옵션이 일치하지 않는 인수보다 먼저 발생하는지 여부입니다. 따라서 --flagarg 목록에서 발생 하면 트리거 flag=1됩니다. 이것은 복합적인 것이 --flag --flag --flag아니라 얻는 것 flag=1입니다. 이 값 뒤에 오는 모든 인수에 대해 증가합니다. 인덱스 키로 사용할 수 있습니다. eval위의 작업을 수행 한 후에는 다음을 수행 할 수 있습니다.

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

…를 얻기 위해 …

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 = 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