Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 混合“;名词集;加上$@&引用;以ksh为单位_Shell_Ksh - Fatal编程技术网

Shell 混合“;名词集;加上$@&引用;以ksh为单位

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 &

我有一个脚本,需要将其所有参数转发到不同的程序。此外,出于清洁目的,我保持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
<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 "${@:-}"