bash 中的命令替换和算术扩展的顺序

问题描述 投票:0回答:2

《学习 bash Shell》第三版。 Cameron Newham 和 Bill Rosenblatt 在第 181 页有一张描述 bash shell 命令行处理的图片。该图显示,命令替换是在算术替换(原文如此)之前执行的。不过,bash 手册页报告了不同的顺序:“扩展的顺序是:大括号扩展;波形符扩展、参数和变量扩展、算术扩展命令替换(以从左到右的方式完成);分词;和路径名扩展。”书上有错吗?如果是的话,你能提供一个例子来证明它吗?

bash command-line substitution expansion command-substitution
2个回答
3
投票

官方文档是正确的(但请注意其中“”和“;”之间的细微差别):

命令替换

$()
/
``
和算术替换
$(())
具有 相同的优先级。当阅读从左到右时,无论先出现什么,都会先展开。

您可以通过测试来确认这一点。在这里,我们使用内置变量

$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

1
投票

首先,根据bash官方文档顺序如下:

将命令行拆分为令牌后进行扩展。执行的扩展有七种:

  1. 支架扩张
  2. 波形符扩展
  3. 参数和变量扩展
  4. 命令替换
  5. 算术扩展
  6. 分词
  7. 文件名扩展

展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和文件名扩展。

正如@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
© www.soinside.com 2019 - 2024. All rights reserved.