長いオプションを処理するには、getoptsを使用してください。

長いオプションを処理するには、getoptsを使用してください。

オプションを解析していますが、getopts長いオプションも処理したいと思います。

print-args ()
{
 title="$1" ; shift
 printf "\n%s\n" "${title}: \$@:"
 for arg in "$@"; do
   (( i = i + 1 ))
   printf "%s |%s|\n" "${i}." "$arg"
 done
}

getopts_test ()
{
 aggr=()
 for arg in "$@"; do
   case $arg in
    ("--colour"|"--color")     aggr+=( "-c" ) ;;
    ("--colour="*|"--color="*) aggr+=( "-c" "${arg#*=}" ) ;;
    (*)  aggr+=( "$arg" ) ;;
   esac
 done

 print-args "print" "$@"

 eval set -- "${aggr[@]}"
 print-args "eval" "$@"

 set -- "${aggr[@]}"
 print-args "set" "$@"

 local OPTIND OPTARG
 local shortopts="C:"
 while getopts "$shortopts" arg; do
   case $arg in
    ("c") context="$OPTARG" ;;
    (*) break ;;
   esac
 done
 shift $(( OPTIND - 1 ))
}

ところで使い方が合っているか知りたいですset -- "${aggr[@]}"

それとも、次の(を使用してeval)がより適切ですか?

eval set -- "${aggr[@]}"

以下のようにテストを行いました。文字列 "Gunga Din"はevalを使用すると分割されますが、evalを使用すると単一のset -- "${aggr[@]}"文字列に正しく解析されます。

getopts_test -f -g 130 --colour="170 20" "Gunga Din"

print: $@:
1. |-f|
2. |-g|
3. |130|
4. |--colour=170 20|
5. |Gunga Din|

eval: $@:
1. |-f|
2. |-g|
3. |130|
4. |-c|
5. |170|
6. |20|
7. |Gunga|
8. |Din|

set: $@:
1. |-f|
2. |-g|
3. |130|
4. |-c|
5. |170 20|
6. |Gunga Din|

その後、非GNUを使用して他の機能を実行しましたgetopt

getopt_test ()
{
 shortopts="Vuhv::H::w::e::n::l::C:"
 shortopts="${shortopts}bgcrmo"
 longopts="version,usage,help,verbosity::"
 longopts="${longopts},heading::,warning::,error::"
 longopts="${longopts},blu,grn,cyn,red,mgn,org"
 
 opts=$( getopt -o "$shortopts" -l "$longopts" -n "${0##*/}" -- "$@" )

 print-args "\$@:" "$@"
 print-args "opts:" "$opts"

 set -- "$opts"
 print-args "set -- \"$opts\"" "$@"

 eval set -- "$opts"
 print-args "eval set -- \"$opts\"" "$@"

}

結果は次のとおりです。

getopt_test --warning=3 "foo'bar" "Gunga Din"

$@:
1. |--warning=3|
2. |foo'bar|
3. |Gunga Din|

opts:
1. | --warning '3' -- 'foo'\''bar' 'Gunga Din'|

set -- "$opts"
1. | --warning '3' -- 'foo'\''bar' 'Gunga Din'|

eval set -- "$opts"
1. |--warning|
2. |3|
3. |--|
4. |foo'bar|
5. |Gunga Din|

示されているように、getoptの結果は位置パラメータが再配置された項目です。これは、オプションの解析と処理のためにeval set -- "$opts"文字列の位置パラメータをopts5つの項目に分割する必要があることを示します。

ベストアンサー1

アイデアは、パラメータを前処理し、各パラメータを--context処理できるパラメータに変更することです-Cgetopts私はこれがうまくいくと思いますが、GNUスタイルの長いオプションはフォーマットの引数を取ることができ、--context=foobarここではあなたの設定はサポートしていません。ここでは、この特定のツールに2つの異なるパラメータが必要であることを知っておく必要があります--context foobar。あるいは、前処理をより複雑にする必要があります。

で始まるすべてのパラメータを確認したい場合があります--。それ以外の場合は、誤字が発生したままで不明なオプションに関する苦情が表示されます--cotnextgetopts(または悪い場合は無効なオプションが有効になります。)

ところで使い方が合っているか知りたいですset -- "${aggr[@]}"

それとも、次の(evalを使用)がより適切ですか?

set -- "${aggr[@]}"配列の要素を別の単語に展開し、その単語を位置パラメータに割り当てます。各配列要素は正確に1つの位置パラメータになり、変更する必要はありません。

eval set -- "${aggr[@]}"配列内のすべての要素は展開され、スペースで連結され、先頭に追加され、set -- 結果はシェルコマンドによって評価されます。つまり、配列要素、、、abc def$(date >&2)ある場合、ghi'jklコマンドは次のようになります。

set -- abc def $(date >&2) ghi'jkl 

abcこれは、2つの異なる引数で終わり、単一def引用符だけで構文エラーが発生することを除いて、日付をstderrに出力します。

evalシェルへの入力として引用された出力を生成するように設計されたものがある場合は、それを使用することが適切です。


Linuxを使用していて移植性に興味がない場合は、roaimaが説明のように実行し、util-linuxバージョンgetopts)を使用できます。長いオプションもサポートされており、使用方法を示す答えがあります。getopt、getopts、または手動解析 - 短いオプションと長いオプションの両方をサポートするには何を使用する必要がありますか?そしてこの回答そして私の答えはここにあります

さて、getoptあなたは会議コマンドevalとして、配列などのリストではなく単一の文字列を出力として生成することに制限されているため、シェル引用符を使用して問題を解決します。

おすすめ記事