在 Bash 和 Dash 中,在算术扩展中使用引号是非法的:
$ bash -c 'x=123;echo $(("$x"))'
bash: "123": syntax error: operand expected (error token is ""123"")
$ dash -c 'x=123;echo $(("$x"))'
dash: 1: arithmetic expression: expecting primary: ""123""
当作为 sh 调用时,Bash 会给出相同的错误。不过 Ksh 和 FreeBSD 的 Bourne Shell 并不介意:
$ ksh -c 'x=123;echo $(("$x"))'
123
$ sh -c 'x=123;echo $(("$x"))'
123
根据Bash 参考手册:
该表达式被视为位于双引号内,但括号内的双引号不会被特殊处理。所有代币......都会经历......报价删除。
(本质上与POSIX说。)
最后,与其他算术上下文(例如条件表达式)$(( ))
相比,Bash 的处理方式有所不同。(( ))
后者带有引号就可以了。
要么我不明白什么报价删除意味着此处,或者这是其中一些 shell 实现中的错误。如果是前者,“删除引号”到底意味着什么?或者,这只是一个错误?
答案1
我很困惑这是一个糟糕的实现还是糟糕的文档。 Bash 对于引用删除是这样说的:
报价删除
在前面的扩展之后,所有未加引号的字符
\
、'
、 和"
不是由上述扩展之一产生的都将被删除。
我认为关键可能是“所有未引用的该段落中的所有内容$(( ))
都被视为用双引号括起来。如果这些字符位于括号内,则它们都会被引用,从而使引号删除本质上是一个空操作。例如,请注意其他“删除”的方式" 处理字符(另请注意如何保留尾随空格,因为如何解析带引号的字符串):
$ echo $(( '5' ))
bash: '5' : syntax error: operand expected (error token is "'5' ")
$ echo $(( \ ))
bash: \ : syntax error: operand expected (error token is "\ ")
浏览源代码,引号确实需要平衡,因为代码会扫描以确定是$(( ))
数学还是嵌套的遗留子表达式。当字符串被识别为算术表达式时,它会被解析为双引号 - 这意味着全部在删除引号之前,内部的字符被视为被引用。
就我个人而言,这就是我更喜欢 ksh 的部分原因 - 特别是对于数学。例如,它将上面的单引号 5 视为 C 字符串,其计算结果为 53。 man ascii
看看为什么这是有道理的。 :)