Cit*_*ght 69 shell shell-builtin
据我所知,[[
是 的增强版本[
,但是当我将其[[
视为关键字并[
显示为内置时,我感到困惑。
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
Run Code Online (Sandbox Code Playgroud)
TLDP说
内置命令可能是同名系统命令的同义词,但 Bash 在内部重新实现了它。例如,Bash echo 命令与 /bin/echo 不同,尽管它们的行为几乎相同。
和
关键字是保留字、标记或运算符。关键字对 shell 有特殊的意义,实际上是 shell 语法的构建块。例如,for、while、do 和 ! 是关键字。与内置函数类似,关键字被硬编码到 Bash 中,但与内置函数不同的是,关键字本身不是命令,而是命令结构的子单元。[2]
难道不应该使双方[
和[[
关键字?有什么我在这里想念的吗?此外,此链接再次确认两者[
和[[
应该属于同一类。
Joh*_*024 85
[
和之间的区别[[
是非常根本的。
[
是一个命令。它的参数的处理方式与处理任何其他命令参数的方式相同。例如,考虑:
[ -z $name ]
Run Code Online (Sandbox Code Playgroud)
外壳将扩大$name
并进行双方对结果分词和文件名的产生,只是因为它会为任何其他命令。
例如,以下将失败:
$ name="here and there"
$ [ -n $name ] && echo not empty
bash: [: too many arguments
Run Code Online (Sandbox Code Playgroud)
为了使这项工作正常进行,引号是必要的:
$ [ -n "$name" ] && echo not empty
not empty
Run Code Online (Sandbox Code Playgroud)[[
是一个 shell 关键字,它的参数根据特殊规则进行处理。例如,考虑:
[[ -z $name ]]
Run Code Online (Sandbox Code Playgroud)
外壳将扩大$name
,但是,不同于其他任何命令,它将执行没有分词,也没有对结果文件名生成。例如,尽管在 中嵌入了空格,但以下内容仍会成功name
:
$ name="here and there"
$ [[ -n $name ]] && echo not empty
not empty
Run Code Online (Sandbox Code Playgroud)[
是一个命令,与 shell 执行的所有其他命令遵循相同的规则。
因为[[
是关键字,而不是命令,shell 对其进行了特殊处理,并且在非常不同的规则下运行。
War*_*ung 63
在V7 Unix中——Bourne shell 首次亮相的地方——[
被称为test
,它仅作为/bin/test
. 所以,你今天要写的代码是:
if [ "$foo" = "bar" ] ; then ...
Run Code Online (Sandbox Code Playgroud)
你会写成
if test "$foo" = "bar" ; then ...
Run Code Online (Sandbox Code Playgroud)
这第二个符号仍然存在,我发现它更清楚发生了什么:您正在调用一个名为 的命令test
,该命令评估其参数并返回一个退出状态代码,if
用于决定下一步做什么。该命令可能内置在 shell 中,也可能是一个外部程序。¹
[
作为test
后来的替代。² 它可能是 的内置同义词test
,但它也作为/bin/[
现代系统提供,用于没有内置它的 shell。
[
并且test
可以使用相同的代码实现。对于OS X/bin/[
和/bin/test
在 OS X 上都是这种情况,其中这些是指向同一可执行文件的硬链接。³ 因此,实现完全忽略了尾随]
:如果您将其称为/bin/[
,则不需要它,并且它不会抱怨如果你做的是提供/bin/test
?
这段历史没有任何影响[[
,因为从来没有一个原始程序被调用[[
。它纯粹存在于那些将它实现为POSIX shell扩展的shell 中。
“内置”和“关键字”之间的部分区别是由于这段历史。它还反映了解析[[
表达式的语法规则不同的事实,如John1024 的回答.?
脚注:
当你这样看待它时,它清楚地表明为什么你必须[
在 shell 脚本中放置空格,这与大多数其他编程语言中的括号和方括号的工作方式不同。如果 shell 的命令解析器允许if["$x"...
,它也必须允许iftest"$x"...
它发生在 1980 年左右。/bin/[
在我1979 年的古代 Unix V7副本中不存在,也没有将其man test
记录为别名。在相应的手册页条目我在一个预发布副本系统III从1980年手册,它是上市。
ls -i /bin/[ /bin/test
但不要指望这种行为。在Bash内建的版本[
确实需要关闭]
,并且其内置的test
实施将抱怨,如果你不提供。
内置命令与外部命令的区别可能还有另一个原因:这两种实现的行为可能不同。echo
许多系统都是这种情况。因为只有一种实现,所以不需要对关键字进行这样的区分。