《学习 bash Shell》第三版。 Cameron Newham 和 Bill Rosenblatt 在第 181 页有一张描述 bash shell 命令行处理的图片。该图显示,命令替换是在算术替换(原文如此)之前执行的。不过,bash 手册页报告了不同的顺序:“扩展的顺序是:大括号扩展;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。”书上有错吗?如果是的话,你能提供一个例子来证明它吗?
官方文档是正确的(但请注意其中“,”和“;”之间的细微差别):
命令替换
$()
/``
和算术替换 $(())
具有 相同的优先级。当阅读从左到右时,无论先出现什么,都会先展开。
您可以通过测试来确认这一点。在这里,我们使用内置变量
$SECONDS
,它包含自 bash 启动以来的时间(以秒为单位)。
#! /bin/bash
echo "$(sleep 1; echo "command $SECONDS"; sleep 1), arithmetic $((SECONDS))"
echo "arithmetic $((SECONDS)), $(sleep 1; echo "command $SECONDS"; sleep 1)"
此打印
command 1, arithmetic 2
arithmetic 2, command 3
首先,根据bash官方文档顺序如下:
将命令行拆分为令牌后进行扩展。执行的扩展有七种:
展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和文件名扩展。
正如@socowi在他的回答中指出的那样,在操作顺序方面,
;
和,
之间存在差异,因此第2-5种是从左到右同时完成的。
正如您怀疑的那样,您的书是错误的。 现在,我最初怀疑如果算术扩展后发生命令替换,我们可能会遇到如下情况:
uberhumus@homepc:~$ kuki=$(echo "if command substitution happens before arithmetic substitution, this $((2+3)) is 5 else it's 2+3")
uberhumus@homepc:~$ echo $kuki
if command substitution happens before arithmetic substitution, this $((2+3)) is 5 else it's $((2+3))
这是错误的。由于
(echo "if command substitution happens before arithmetic substitution, this $((2+3)) is 5 else it's 2+3")
本身就是一个命令,这意味着扩展命令也发生在其中,因此这种情况是不可能的。
事实上,如果您在上述实验之前运行
set -vx
,您可以看到,作为最里面的扩展,$((2+3))
立即执行。
uberhumus@homepc:~$ set -vx
uberhumus@homepc:~$ kuki=$(echo "if command substitution happens before arithmetic substitution, this $((2+3)) is 5 else it's 2+3")
kuki=$(echo "if command substitution happens before arithmetic substitution, this $((2+3)) is 5 else it's 2+3")
++ echo 'if command substitution happens before arithmetic substitution, this 5 is 5 else it'\''s 2+3'
+ kuki='if command substitution happens before arithmetic substitution, this 5 is 5 else it'\''s 2+3'
uberhumus@homepc:~$ echo $kuki
echo $kuki
+ echo if command substitution happens before arithmetic substitution, this 5 is 5 else 'it'\''s' 2+3
if command substitution happens before arithmetic substitution, this 5 is 5 else it's 2+3