Bash [和[]之间的八进制膨胀差?
据我所知,Bash [和[]之间的八进制膨胀差?,bash,sh,octal,Bash,Sh,Octal,据我所知,[和[的行为基本相同,考虑到[[的一些额外特性。但最近我注意到bash处理八进制扩展的方式存在差异: $ b=010; echo $((b)) 8 $ [[ $b -eq 8 ]]; echo $? 0 但是 为什么后一个表达式会放弃自动八进制转换?类似于-eq的表达式根据Bash和中的help test是“算术”的,进一步根据参考手册的下一节,前导零的常数可以被视为八进制 POSIX sh有点不太清楚:尽管POSIX算术表达式仍然将前导零整数扩展到其八进制值,但它将测试中的-eq表
[
和[
的行为基本相同,考虑到[[
的一些额外特性。但最近我注意到bash处理八进制扩展的方式存在差异:
$ b=010; echo $((b))
8
$ [[ $b -eq 8 ]]; echo $?
0
但是
为什么后一个表达式会放弃自动八进制转换?类似于-eq
的表达式根据Bash和中的help test
是“算术”的,进一步根据参考手册的下一节,前导零的常数可以被视为八进制
POSIX sh有点不太清楚:尽管POSIX算术表达式仍然将前导零整数扩展到其八进制值,但它将测试中的-eq
表达式称为代数表达式,而不是算术表达式
是否有任何文档或证据表明bash故意将八进制扩展区分为[[
和[
,或者这只是一个偶然的特性?[[被称为扩展测试命令,其行为与ksh88相同,您可以在这里找到详细说明:
此外,如果需要确保bash中的base,可以使用如下#base操作符:
b=010; echo $((10#$b))
10
b=10; echo $((8#$b)
8
b=013; echo $((8#$b))
11
+1、 但我注意到,尽管-eq
被描述为“算术二进制运算符”,但它的参数并没有被描述为“算术表达式”
不会扩展shell参数$b
。因此,虽然该操作符将010
视为表示8而不是表示10更有意义,但我在手册中没有看到任何与您看到的行为相矛盾的内容。[[b-eq 8]]
似乎等同于((b==8))
(您可以省略$
)。文档中似乎没有这样说。@choroba很好的一点,我甚至没有意识到[[x-eq y]]
像(())
表达式一样展开x和y。自从您提出它以来,我尝试了[[9-1-eq b]
,退出状态为0。所以在[[[…-eq…]]
bash清楚地推断出一个算术上下文。如图所示。这是一个众所周知的特性(或者应该是),而且算术上下文(无论是与(…)
还是[[…-eq…]]
)都可能导致代码注入。例如,一个有趣的特性:a='a[$(ls>&2)];如果[$a-eq 42]];然后echo yes;fi
。谢谢,我将+1这个,因为TLDP链接实际上在我的问题中直接提到了差异。也就是说,ksh93显然没有在$(())
中进行八进制扩展,这使得它甚至与POSIX sh不同。(我手头没有ksh88,但可能有人可以对此进行评论。)哦,奇怪的是,ksh93确实将带前导零的文本视为八进制,但在扩展时不这样做。echo$(010))->8
,但是x=010;echo$((x))->10
。我可以看出这种行为如何被认为是与POSIX兼容的。不是这样,但如果您x=010;echo$($x))
你应该得到8。这实际上令人困惑。我的意思是你可以清楚地知道ksh是如何对表达式进行词法分析的,但是POSIX说shell应该在[算术]中扩展所有标记用于参数扩展、命令替换和引号删除的表达式。它没有说它应该将lex$x
作为一个独立的扩展,然后将扩展后的010
视为八进制文字。我同意它看起来很奇怪,并且与您引用的POSIX语句不符。如果您需要,最好检查源代码我想看看发生了什么-但不这样做-我猜ksh
是在表达式之前扩展变量,所以在$x
的情况下,它不知道/不关心$x
是算术表达式的一部分,它是一个第一次扩展,只是将其扩展为字符串文本010casex
看起来扩展是由另一个代码段处理的,该代码段会自动转换为十进制。
b=010; echo $((10#$b))
10
b=10; echo $((8#$b)
8
b=013; echo $((8#$b))
11