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
是算术表达式的一部分,它是一个第一次扩展,只是将其扩展为字符串文本010case
x
看起来扩展是由另一个代码段处理的,该代码段会自动转换为十进制。
b=010; echo $((10#$b))
10
b=10; echo $((8#$b)
8
b=013; echo $((8#$b))
11