web-dev-qa-db-ja.com

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'
4

オプションの解析中にgetoptが行う多くのことの1つは、引数を再配置することです。これにより、オプション以外の引数が最後になり、結合された短いオプションが分割されます。 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を使用すると、スクリプト引数になります。

shiftについては、常に最初の引数を削除し、shiftすべての引数を削除します(これにより、$2は、 $1)。これにより、処理された引数が削除されるため、このループの後はオプション以外の引数のみが残り、オプションを気にすることなく$@を簡単に使用できます。

6
muru