Bash:为什么在解析命令行参数的脚本中使用 eval 和 shift?

Dim*_*las 7 bash shell-script getopts eval

当我在看这个答案/sf/answers/774563751/以弄清楚如何使用参数时,--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
Run Code Online (Sandbox Code Playgroud)

首先,shift以下行中的程序做了什么:

        -a|--a-long) echo "Option a" ; shift ;;
Run Code Online (Sandbox Code Playgroud)

之后eval在以下行中使用命令的目的是什么:

eval set -- "$TEMP"
Run Code Online (Sandbox Code Playgroud)

我试图评论上面提到的脚本中的行,我得到了以下回复:

$ ./getOptExample2.sh  -a 10 -b 20 --a-long 40 -charem --c-long=echi
Param: -a
Option a
Param: 10
Internal error!
Run Code Online (Sandbox Code Playgroud)

但是,如果我取消注释它,它就像一个魅力:

Option a
Option b, argument `20'
Option a
Option c, argument `harem'
Option c, argument `echi'
Remaining arguments:
--> `10'
--> `40'
Run Code Online (Sandbox Code Playgroud)

mur*_*uru 9

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.
Run Code Online (Sandbox Code Playgroud)

这种效果反映在您的代码中,其中选项处理循环假定所有选项参数(包括选项的参数)首先出现,然后单独出现,最后是非选项参数。

因此,TEMP包含重新排列、引用、拆分的选项,并使用eval set使它们成为脚本参数。

至于shift,它做它一直做的事情:删除第一个参数,并移动所有参数(以便$2现在是$1)。这消除了已处理的参数,因此,在此循环之后,只剩下非选项参数,您可以方便地使用$@而无需担心选项。