运行Shell脚本时,是否可以传递特定的位置参数而不必依次输入所有位置参数?


13

例如,如果我的脚本./foo具有10个参数,而我只想传递第8个参数。我目前知道如何执行此操作的唯一方法是:

./foo '' '' '' '' '' '' '' 'bar'

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


1
这就是为什么如果您有很多参数,则程序通常使用选项而不是位置参数的原因。
Barmar 2014年

Answers:


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

输出值

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

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

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

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

...而前一行完全省略了,但是我想证明以这种方式声明变量的确会产生持久值,因此我用两个命令做到了。两种方法$eight都将设置为该复合参数扩展的最终值。

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

例如:

touch file$(seq -ws\ file 100)
./foo *

输出值

$eight = file008

在这里,我们只看到第八个操作数,但是从我的测试目录中可以看到其中的101个。


18

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

如果您将前七个参数中的每个七个作为选项,并将它们默认设置为空字符串,则可以执行以下操作:

./foo bar

如果使用兼容POSIX的外壳,则可以使用getopts实用程序或程序getoptbash像大多数外壳getopts一样,作为内置产品提供。每种方法都比滚动您自己的命令行解析器容易。

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


5
+1getopt(s)。位置参数是一个悲伤的时刻,应避免使用。
HalosGhost 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.