考虑在 bash 命令行中输入以下代码片段:
$ echo $(( $(wc -l letter.txt | cut -c1-4)/66 + 1))
假设letter.txt
存在并且有 66*4 行,那么这会将字符串 5 放在命令行上。现在我无法理解的是,根据我对命令行处理的了解,这个结论是如何得出的。
我的书(索贝尔的Linux 实用指南,4e)说
Bourne Again Shell 按以下顺序扫描每个标记以查找各种类型的扩展和替换。大多数这些过程将单词扩展为单个单词。只有大括号扩展、单词分割和路径名扩展可以更改命令中的单词数(变量“$@”的扩展除外 - 参见第 474 页)。
- 支撑扩展(下一页)
- 波形符扩展(第 368 页)
- 参数和变量扩展(第 368 页)
- 算术展开(第369页)
- 命令替换(第 371 页)
- 分词(第 372 页)
- 路径名扩展(第 372 页)
- 进程替换(第 374 页)
- 删除报价(第 374 页)
根据上述内容,算术扩展似乎会首先求值,如果是这样,则令牌$(wc -l letter.txt | cut -c1-4)
对于 bash 处理的整数算术来说不是有效的操作数。我的出路是什么/我不明白什么?
答案1
你的书不完全正确。man bash
具体顺序请参见:
展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。
注意逗号和的用法分号。参数、变量和算术扩展以及命令替换都以相同的顺序发生。
手册中关于算术扩展的说明如下:
表达式中的所有标记都会经历参数和变量扩展、命令替换和引号删除。
命令替换描述为
...在子shell环境中执行命令
这意味着所有扩展都是在从内向外嵌套时发生的。
$ echo $((1 + $(echo $((2+$(printf %s 3))))))
6