Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么bash大括号扩展在某些算术表达式中有效,而在其他表达式中无效?_Bash_Brace Expansion - Fatal编程技术网

为什么bash大括号扩展在某些算术表达式中有效,而在其他表达式中无效?

为什么bash大括号扩展在某些算术表达式中有效,而在其他表达式中无效?,bash,brace-expansion,Bash,Brace Expansion,我正在编写一个非常简单的bash脚本,我有一个问题,那就是为什么不推荐的$[]可以完美地工作,而$(())似乎破坏了整个过程 我指的代码是: for i in {1..10}; do printf %4d $[{1..10}*i] echo done 在这个版本中,我没有问题,但我不想使用不推荐的bash元素,这就是为什么我想切换到$(()) 不幸的是,一旦我将代码更改为: printf %4d $(({1..10}*i)) 我收到一个错误: ./script_bash.s

我正在编写一个非常简单的bash脚本,我有一个问题,那就是为什么不推荐的$[]可以完美地工作,而$(())似乎破坏了整个过程

我指的代码是:

for i in {1..10};
do 
    printf %4d $[{1..10}*i]
    echo
done
在这个版本中,我没有问题,但我不想使用不推荐的bash元素,这就是为什么我想切换到$(())

不幸的是,一旦我将代码更改为:

printf %4d $(({1..10}*i))
我收到一个错误:

./script_bash.sh: line 8: {1..10}*i: syntax error: argument expected (error token is "{1..10}*i")
我非常感谢您在这方面的帮助。

$(())
用于算术表达式,而大括号扩展不是在算术中完成的

使用循环创建一个数组:

for i in {1..10}
do
    vals=()
    for j in {1..10}
    do
        vals+=($((i*j)))
    done
    printf "%4d" ${vals[@]}
done

为1990年的回归设定了一条道路

Bash根据POSIX P1003.2d9(大约1990年)实现了
$[]
语法,这是已发布的P1003.2-1992的草案。在草稿和标准之间的两年时间里,POSIX取而代之的是ksh88
$(())
语法和行为。Chet Ramey(bash维护人员)说:

猛击。。。实现了$[…],因为没有其他 语法,并获得一些操作经验 外壳中的算术展开。Bash-1.14。。。列出两种形式的算术展开,但按 1995年发布bash-2.0时,手册只提到 美元(…)表格

这向我表明,
$[]
形式是实验性的,当POSIX采用
$(())
语法时,它具有某些行为(如大括号扩展)被指定为遗忘。这些实验行为被保留了下来,因为在野外已经有脚本依赖于它们(请记住,2年多过去了)

Chet在同一个线程中明确指出,
$[]
表单已过时,但未弃用:

现在,继续拖动$[…]语法几乎没有什么问题。 它只需要几十个字节的代码。我不打算把它移走

其中提到了语法(我的重点):

在早期的提案中,使用了$[表达式]形式它在功能上等同于当前文本的“$(())”,但有人反对1988年的KornShell已经实现了“$(())”,并且没有令人信服的理由发明另一种语法。此外,“$[]”语法有一点不兼容,涉及case语句中的模式

因此,bash中实现的行为并不完全符合规范,但由于没有删除它的计划,如果它能巧妙地解决您的问题,我认为没有理由放弃它的好处。然而,正如@Barmar的评论所指出的,最好对代码进行注释并将其链接到此处,以便未来的开发人员了解您的意思

printf%4d$({1..10}*i))

由于参数在
bash
中的展开顺序,因此无法工作。大括号扩展(
{}
)比算术扩展(
$(())
)早于
bash
完成。如果换个角度看,你的代码肯定能工作

manbash

展开顺序为:支撑展开;波浪线展开、参数和变量展开、算术展开和命令替换(以从左到右的方式完成);分词;和路径名扩展


遇到这样的狂欢。这个问题要求解释,而不是解决,但这里有一个$(())的表达方式

for i in {1..10}; do
  printf %4d $(eval echo '$(('{1..10}'*i))')
  echo
done
大括号展开在算术展开中被禁止,就像参数展开一样

(bash手册)

为避免与参数扩展冲突,不使用字符串“${” 被认为有资格扩展支撑,并禁止扩展支撑 直到结束“}”


$(())
是一个算术表达式。它不进行常规的通配符或大括号扩展。但是,另一方面,为什么大括号扩展在
$[]
中进行?这是我第一次听说
$[]
。我在bash手册中找不到它。它是一个不推荐使用的伪等价物,相当于
$(
,请看,我猜从技术上讲,您的第一句话是不正确的,因为表面上
$[]
也是“算术表达式”的意思但我猜想,在他们创建它的时候,他们并没有认为算术扩展与它自己的语法完全不同的上下文。虽然它没有明确地被弃用(实际上有一个被弃用的特征列表吗?),事实上,手册中甚至没有提到它,这是避免它的一个强有力的指示。即使它从未真正消失,其他程序员也不会理解它。我已经编写了30年的shell脚本,我以前从未看到过这一点,我相信我并不孤单。与您链接的bash hackers页面上的其他功能相比到目前为止,它们仍然在手册中。@Barmar当前的POSIX规范中提到了它,一些发行版修补了bash手册页来提及它。尽管如此,我已经详细阐述了我的用法“建议”。