运行 shell 脚本时,是否可以传递特定的位置参数而不必按顺序输入它们?

Ker*_*lph 13 parameter shell-script

例如,如果我的脚本 ./foo 有 10 个参数,而我只想传递第 8 个参数。我目前知道如何做到这一点的唯一方法是:

./foo '' '' '' '' '' '' '' 'bar'
Run Code Online (Sandbox Code Playgroud)

有没有更简单/更好的方法?

Ant*_*hon 18

假设您可以更改脚本,您应该考虑使用可选参数(options)而不是必需参数(arguments)。

如果您将前 7 个七个参数中的每一个作为选项,并将它们默认为空字符串,那么您可以这样做:

./foo bar
Run Code Online (Sandbox Code Playgroud)

如果您使用与POSIX 兼容的 shell,则可以使用该getopts实用程序或程序getopt. bash- 像大多数贝壳一样 -getopts作为内置提供。无论哪种方式都比滚动您自己的命令行解析器更容易。

除非您实现类似最后一个 X 非选项参数的值是最后一个 Y 参数和 XY 选项参数的值,否则您必须在 7 个(现在为空)字符串中的每一个之前提供选项字符串,如果您想设置其中任何一个。然而,这不是常见的做法,通常一个选项总是一个选项,一个参数总是一个参数,并且选项“插入”的顺序是自由的。

  • `getopt(s)` 的 `+1`。位置参数是一个悲伤的时刻,应该避免。 (5认同)

mik*_*erv 4

执行此操作的另一种方法是命名要声明的参数,然后执行以下操作:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT
Run Code Online (Sandbox Code Playgroud)

输出

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,显式声明的环境变量优于命令行参数,但当环境变量为空或未设置时,将使用命令行参数。当第 8 个位置变量环境变量$eight都为空或未设置时,默认值some_default被分配给$eight。在任何一种情况下,如果空应该是可接受的值,则可以从or语句:中删除。:-:=

该变量$eight也可以设置为:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"
Run Code Online (Sandbox Code Playgroud)

...前一行完全省略,但我想证明以这种方式声明变量确实会产生持久值,所以我用两个命令完成了它。无论哪种方式$eight都设置为该复合参数扩展的最终值。

getopts- 对于健壮的脚本 - 通常是处理命令选项的最佳方法。另一方面,位置参数几乎总是鲁棒地处理脚本中操作数的最简单方法。

例如:

touch file$(seq -ws\ file 100)
./foo *
Run Code Online (Sandbox Code Playgroud)

输出

$eight = file008
Run Code Online (Sandbox Code Playgroud)

在那里我们只看到了第八个操作数,但从我的测试目录中找到了其中的 101 个操作数。