getopt
bashコマンドラインにコマンドがあります。getopt
これは短いオプション(例getopt -o axby "$@"
:)で機能し、短くて長いオプション(例getopt -o axby -l long-key -- "$@"
:)では機能しますが、今は必要です。ただ長いオプション(つまり、短いオプションはまったく存在しません)ですが、コマンドはオプションを正しく解析できませgetopt -l long-key -- "$@"
ん。それでは、コマンドを--long-key
どのように使用できますか?getopt
ただ長いオプション?それともこれは不可能ですか、それともコマンドのバグですかgetopt
?
答え1
getopt
短期的なオプションがなくても大丈夫です。しかし、短期的なオプションはないと言うべきです。これはマニュアルの珍しい構文です。
最初の部分にno
-o
またはoptionがない場合、--options
2番目の部分の最初の引数は短いオプション文字列として使用されます。
これがテストで起こるものです。これをオプションのリストで唯一のパラメータ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
これは私が使用する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 配列を 1 つのセットまたは区切り文字で区切られた 2 つの引数のセットに渡すかどうかに応じて、2 つの方法のいずれかで処理します。どちらの場合も、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 -- "$@")"
...絶対に安全でなければなりません。何らかの理由でいいえセキュリティを確保するには、シェル管理者にバグレポートを送信する必要があります。
各一致に 2 つのエイリアス値を割り当てます。まず、フラグを設定します。これは、オプションが一致しない引数の前にあるかどうかに関係なく発生します。したがって、--flag
引数リストのすべての項目がトリガーされます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