内置冒号“:”有什么作用?

内置冒号“:”有什么作用?

我已经破解了很多 shell 脚本,有时最简单的事情也让我感到困惑。今天我遇到了一个广泛使用:(冒号)bash 内置函数的脚本。

文档看起来很简单:

: (a colon)  
     : [arguments]  

除了扩展参数和执行重定向之外,不执行任何操作。返回状态为零。

然而我以前只在 shell 扩展的演示中看到过它的使用。我遇到的脚本中的用例广泛使用了这种结构:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

实际上有数百个 grep,但它们只是更多相同。除了上面的简单结构之外,不存在输入/输出重定向。稍后在脚本中不会检查返回值。

我将其视为一个无用的结构,即“或什么都不做”。用“或什么也不做”结束这些 grep 可以达到什么目的?在什么情况下,这种构造会导致与简单地|| :从所有实例中删除 不同的结果?

答案1

内置命令:对于 Bash“分配默认值”shell 扩展也很有用,其中扩展通常仅用于副作用,而扩展的值会被丢弃:

# assign FOO=bar iff FOO is unset or empty
: "${FOO:=bar}"

答案2

看来:您的脚本中的 s 正在用来代替true.如果grep在文件中没有找到匹配项,它将返回一个非零退出代码;正如 jw013 在评论中提到的,如果errexit设置了(可能是在 shebang 行),如果任何一个s 找不到匹配项-e,脚本将退出。grep显然,这不是作者想要的,因此他添加了|| :使该特定复合命令的退出状态始终为零的内容,就像更常见的(根据我的经验)|| true/ || /bin/true

答案3

内置:已经在汤普森壳- 它是有记录的为了Unix V61975 年。在 Thompson shell 中,:标出了一个标签goto命令。如果您从未尝试调用goto以 开头的行,则该行实际上是注释。

伯恩外壳,我们所知的 Bourne/POSIX shell 的祖先,据我所知,从未有过 a goto,但保留:为无操作命令(它已经存在于Unix V7),并且它通常用于注释(实际的注释语法#仅在更高版本中添加)。

答案4

我翻出了一本旧参考资料:《UNIX 编程环境》(c) 1984 年,作者:Kernighan 和 Pike。

第 147 页(Shell 编程)是这样说的:

“:”是一个 shell 内置命令,除了计算其参数并返回“true”之外什么也不做。相反,[参考脚本示例],我们可以使用真的,它仅返回真实的退出状态。 (还有一个错误的命令。)但是 ':' 比 true 更有效因为它不执行来自文件系统的命令。 [斜体/强调是我的。]

相关内容