Shell 混合“;名词集;加上$@&引用;以ksh为单位
我有一个脚本,需要将其所有参数转发到不同的程序。此外,出于清洁目的,我保持shell选项Shell 混合“;名词集;加上$@&引用;以ksh为单位,shell,ksh,Shell,Ksh,我有一个脚本,需要将其所有参数转发到不同的程序。此外,出于清洁目的,我保持shell选项nounset处于启用状态 考虑以下示例脚本: #!/bin/ksh set -o nounset # Pass all of our parameters (plus a few extra) to our target printf "<%s>\n" "Parameter count: $#" "$@" 如果禁用nounset选项,我们将得到以下结果: $ ./dollar_at.sh &
nounset
处于启用状态
考虑以下示例脚本:
#!/bin/ksh
set -o nounset
# Pass all of our parameters (plus a few extra) to our target
printf "<%s>\n" "Parameter count: $#" "$@"
如果禁用nounset
选项,我们将得到以下结果:
$ ./dollar_at.sh
<Parameter count: 0>
$./dollar\u at.sh
顺便说一句,bash
下的nounset
处理空的$@
时没有错误,但是此脚本的环境没有bash
作为选项
有没有办法让
ksh
在空$@
的情况下玩得更好?理想情况下,我希望
“$@”
扩展为零参数,就像bash
和ksh
在未启用nounset
的情况下一样
到目前为止,我只提出了两种可能的解决办法,但这两种办法我都不太满意:
if(($#>0))
中,并有条件地传递$@
。我不喜欢这个选项,因为必须始终传递其他常量参数,这会导致重复的代码$@
时,随时切换nounset
选项。这感觉像是一种不好的做法,并且违背了一开始启用nounset
的目的当您保留
集合-o nounoset
时,将特殊处理保留在一个位置:函数
function forwarder {
target=$1
shift
if [ $# -eq 0 ]; then
"${target}"
else
"${target}" "$@"
fi
}
set -u
forwarder ./dollar_at.sh hello world
forwarder ./dollar_at.sh hello
forwarder ./dollar_at.sh ""
forwarder ./dollar_at.sh
变量后面的冒号允许指定默认值。有关详细信息,请参见。脚本运行后,无需保持
nounset
选项处于活动状态。如果需要修改脚本并再次调试,则可以将其添加回。这听起来像是“医生,医生,当我用锤子打我的头时会疼”——处方是一样的:“不要用锤子打你的头”。如果您依赖于设置的环境变量或从配置文件读取的环境变量,那么您可以显式地检查那些重要的环境变量。或者,您可以关闭脚本中调用另一个程序的部分的选项—如您所建议的。我不会测试$#
@JonathanLeffler——这就像告诉Perl用户如果脚本没有抛出错误,就删除使用警告和使用严格的。我不想禁用安全功能,我只想在访问$#==0
和$@
时抑制假警报情况。因此,我不同意与Perl警告/限制进行比较-我从未发现名词集
(好吧,在过去30年左右的shell脚本编写中,我从未觉得有任何必要使用它)。但是,您可以在使用“$”的地方简单地关闭名词集
。我认为如果你不能切换到Bash,那将是最干净的,你说过你不能这样做。@Mr.Llama,使用警告
和使用严格的
实际上是精心设计的,就像Perl中的任何东西一样。set-e
(这比它解决的问题带来了更多的惊喜、歧义和跨版本不兼容),而且有一种情况需要说明,set-o nounset
也不是这样。
function forwarder {
target=$1
shift
if [ $# -eq 0 ]; then
"${target}"
else
"${target}" "$@"
fi
}
set -u
forwarder ./dollar_at.sh hello world
forwarder ./dollar_at.sh hello
forwarder ./dollar_at.sh ""
forwarder ./dollar_at.sh
printf "${@:-}"