${1:+"$@"} in /bin/sh

30
4个回答

29

'Hysterical Raisins'(历史原因的意思),也被称为“Historical Reasons”。

JesperE(或Bash man页面上有关shell parameter expansion的说明)的解释准确描述了其功能:

  • 如果$1存在且不为空字符串,则替换为引用的参数列表。

大约20年前,Bourne Shell的一些损坏的小变体在没有参数的情况下将空字符串""替换为"$@",而不是正确的当前行为-不进行任何替换。这些系统是否仍在使用尚不确定。

[嗯:该扩展对于以下情况无法正常工作:

command '' arg2 arg3 ...

在这种情况下,正确的符号表示法是:
${1+"$@"}

这段代码能够正确工作,无论 $1 是空参数还是非空参数。因此,某人错误地记住了符号,导致意外引入了一个 bug。

7
啊哈,是的,至少根据http://google.com/codesearch,你提到的符号更为常见。我看到${1+"$@"}(即没有冒号)有191,000个结果,而${1:+"$@"}只有173个结果。当然,“man bash”中的引用有一个冒号。所以也许使用冒号不算是一个bug... - ila
4
冒号是一种特殊的测试符号,它用于检查一个字符串是否为空。通常与需要有值的环境变量一起使用,例如:${ENVVAR:+"-value=$ENVVAR"}等等。只有当ENVVAR设置为非空字符串时,才会创建一个-value=whatever参数。 - Jonathan Leffler

4

从bash手册中得知:

   ${parameter:+word}
          Use Alternate Value.  If parameter is null or unset, nothing  is
          substituted, otherwise the expansion of word is substituted.

因此,除非未设置$1,否则将替换"$@"。我不明白为什么他们不能只使用"$@"

顺便说一句:当涉及到这样的问题时,bash man-page 真的是你的好朋友。这可能是我最常用的 man-page。 - JesperE
关于“man bash”,你说得对。抱歉,我也找到了这句话,但没在我的问题里提到它。我同意他们可能只需要使用“$@”,但是${1:+"$@"}肯定有其原因...也许我们会找到答案。 :) - ila
1
我也不排除巫术编程的可能性。;-) - JesperE

3
引用Jonathan Leffler在评论中提到的man bash的相关部分:

当不执行子字符串扩展时,bash会测试一个参数是否为未设置或空值;省略冒号只会测试一个未设置的参数。

(强调是我的)


0

以下是一些其他提示,以便得到更完整的答案...

使用可以涉及 shebang 行,该行从未被彻底记录,并且通常期望有一个单独的参数。

因此,如果文件名包含空格或超过允许的长度,则似乎是一种解决方法。

来自 Perl man page

$* 更好的构造是 ${1+"$@"},它处理文件名中的嵌入式空格等,但如果脚本由 csh 解释,则不起作用。

来自 TCL man page

许多 UNIX 系统不允许 #! 行长度超过约 30 个字符,因此请确保可以使用短文件名访问 tclsh 可执行文件。

最后,一些实用程序可能支持 cat 命令的晦涩但方便的特性

$@ 特殊参数被用作过滤输入到 shell 脚本的工具。cat "$@" 结构接受脚本的输入,可以来自 stdin 或作为脚本参数给出的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接