Bash:コマンドライン引数を解析するスクリプトでevalとShiftを使用するのはなぜですか?

Bash:コマンドライン引数を解析するスクリプトでevalとShiftを使用するのはなぜですか?

私がこの答えを探していたときhttps://stackoverflow.com/a/11065196/4706711--somethingたとえば、パラメータの使用方法や-s回答スクリプトについて尋ねる質問のいくつかを見つけるには、次の手順を実行します。

#!/bin/bash
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n 'example.bash' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -a|--a-long) echo "Option a" ; shift ;;
        -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
        -c|--c-long) 
            # c has an optional argument. As we are in quoted mode,
            # an empty parameter will be generated if its optional
            # argument is not found.
            case "$2" in
                "") echo "Option c, no argument"; shift 2 ;;
                *)  echo "Option c, argument \`$2'" ; shift 2 ;;
            esac ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done

まず、shift次の行のプログラムは何をしますか?

        -a|--a-long) echo "Option a" ; shift ;;

evalそれでは、次のコマンドラインを使用する目的は何ですか?

eval set -- "$TEMP"

上記のスクリプトの対応する行に注釈を付け、次の応答を受けました。

$ ./getOptExample2.sh  -a 10 -b 20 --a-long 40 -charem --c-long=echi
Param: -a
Option a
Param: 10
Internal error!

しかし、コメントを削除すると魅力のように動作します。

Option a
Option b, argument `20'
Option a
Option c, argument `harem'
Option c, argument `echi'
Remaining arguments:
--> `10'
--> `40'

ベストアンサー1

オプションを解析するときに必要な作業の1つgetoptは、オプションではなく引数が最後にあり、結合された短いオプションが分離されるように引数を再配置することです。 ~からman getopt:

Output is generated for each element described in the previous section.
Output is done in the same order as the elements are specified  in  the
input,  except  for  non-option  parameters.   Output  can  be  done in
compatible (unquoted) mode, or in such way that  whitespace  and  other
special  characters  within  arguments  and  non-option  parameters are
preserved (see QUOTING).  When the output is  processed  in  the  shell
script,  it  will  seem to be composed of distinct elements that can be
processed one by  one  (by  using  the  shift  command  in  most  shell
languages).

[...]

Normally, no  non-option  parameters  output  is  generated  until  all
options  and  their  arguments  have  been  generated.   Then  '--'  is
generated as a single parameter, and after it the non-option parameters
in  the  order  they were found, each as a separate parameter.

この効果は、オプションがループを処理するコードに反映されます。仮説すべてのオプション引数(オプション引数を含む)は最初に単独で表示され、最後にオプションではなく引数が続きます。

したがって、TEMP再配置、引用、分割、およびeval setスクリプトパラメータの作成を有効にするオプションが含まれています。

なぜeval?の出力を安全に変換する方法が必要ですgetopt。これは、スペース、'"引用符)*などの特殊文字を安全に処理することを意味します。これを行うには、シェルgetopt が解釈できるように、出力から該当する項目をエスケープします。それ以外の場合はeval唯一のオプションですが、set $TEMPフィールド分割とワイルドカードを介してのみこれを行うことができ、シェルの完全な解析機能は使用できません。

2つの主張があるとしましょう。フィールド分割のみを使用すると、パラメータで使用可能な文字をさらに制限することなく、これら2つの単語を別々の単語として扱うことはできません(たとえば、IFSをに設定した場合、パラメータでは使用:できません)。:したがって、これらの文字をエスケープし、シェルがそのエスケープを解釈できるようにする必要があります。これがまさにevalこれが必要な理由です。何かが大きく間違っていない限りgetopt安全です。


の場合はshift常に行うことを行います。最初の引数を削除して移動するすべてのパラメータ($2現在の内容は$1)です。これにより処理された引数が削除されるため、このループの後にオプションではなく引数だけが残り、$@オプションを気にすることなく便利に使用できます。

おすすめ記事