
getopt
bash 명령줄에 명령이 있습니다 . getopt
짧은 옵션(예: getopt -o axby "$@"
)과 함께 사용할 수 있고 짧은 옵션과 긴 옵션(예: )과 함께 사용할 수 있지만 getopt -o axby -l long-key -- "$@"
이제오직긴 옵션(즉, 짧은 옵션이 전혀 존재하지 않음)이지만 명령은 옵션을 올바르게 getopt -l long-key -- "$@"
구문 분석하지 않습니다 . 그렇다면 어떻게 명령을 --long-key
사용할 수 있습니까 ?getopt
오직긴 옵션? 아니면 불가능합니까, 아니면 단지 명령의 버그입니까 getopt
?
답변1
getopt
짧은 옵션이 없어도 완벽하게 괜찮습니다. 하지만 짧은 옵션이 없다는 점을 알려주어야 합니다. 매뉴얼에서 볼 수 있듯이 구문에 특이한 점이 있습니다.
첫 번째 부분에서 no
-o
또는--options
option이 발견되면 두 번째 부분의 첫 번째 매개변수가 짧은 옵션 문자열로 사용됩니다.
이것이 테스트에서 일어나는 일입니다. 옵션 목록 과 유일한 인수로 getopt -l long-key -- --long-key foo
처리됩니다 . 사용--long-key
-egklnoy
foo
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'
답변2
잘 모르겠지만 내장 기능 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
있습니다 $((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 배열을 처리합니다 --
. 두 경우 모두 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()
문자열로 시작하는 모든 인수에 대한 일치 항목으로 채워집니다 --
.
이 함수는 실제로 모든 처리를 서브쉘에서 수행합니다. 즉, 각 인수의 값을 연관 이름이 할당된 별칭에 반복적으로 저장합니다. 완료되면 저장된 모든 값을 인쇄합니다 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
arg 목록에서 가 발생하면 가 트리거됩니다 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