为什么 bash 大括号扩展在某些算术表达式中起作用,而在其他算术表达式中不起作用?
Why does bash brace expansion work in some arithmetic expressions but not others?
我正在编写一个非常简单的 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 维护者)有话要说,back in 2012:
Bash... implemented $[...] because there was no other
syntax at the time, and to gain some operational experience with
arithmetic expansion in the shell. Bash-1.14... lists both forms of arithmetic expansion, but by
the time bash-2.0 was released in 1995, the manual referred only to
the $((...)) form.
这向我表明 $[]
形式是 实验性的 ,并且它有某些行为(如大括号扩展)在 [=38= 时被指定为遗忘] 采用了 $(())
语法。那些实验性的行为被保留了下来,因为已经有脚本在野外依赖它们(记住已经过去了 2 年多)。
Chet 在同一主题中明确表示 $[]
表格已过时,但并未弃用:
Now, it's hardly any problem to keep dragging the $[...] syntax along.
It takes only a few dozen bytes of code. I have no plans to remove it.
current POSIX standard, C.2.6 Word Expansions > Arithmetic Expansion 提到语法(强调我的):
In early proposals, a form $[expression] was used. It was functionally equivalent to the "$(())" of the current text, but objections were lodged that the 1988 KornShell had already implemented "$(())" and there was no compelling reason to invent yet another syntax. Furthermore, the "$[]" syntax had a minor incompatibility involving the patterns in case statements.
因此 bash 中的实施行为并不完全符合规范,但由于没有删除它的计划,如果它巧妙地解决了您的问题,我认为没有理由放弃它的好处。但是,正如@Barmar 的评论所指出的那样,在此处对代码进行注释并 link 是个好主意,这样未来的开发人员就知道您到底是什么意思了!
printf %4d $(({1..10}*i))
由于参数在 bash
中展开的顺序而不起作用。大括号展开 ({}
) 比算术展开 ($(())
) 早 bash
。如果是其他方式,您的代码肯定会工作。
来自man bash
:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.
运行 像这样 bash。这个问题要求解释,而不是解决方案,但这里将是一种 $(()) 表达方式。
for i in {1..10}; do
printf %4d $(eval echo '$(('{1..10}'*i))')
echo
done
像参数扩展一样,在算术扩展中禁止大括号扩展。
(bash 手动)
To avoid conflicts with parameter expansion, the string ‘${’ is not
considered eligible for brace expansion, and inhibits brace expansion
until the closing ‘}’.
我正在编写一个非常简单的 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 维护者)有话要说,back in 2012:
Bash... implemented $[...] because there was no other syntax at the time, and to gain some operational experience with arithmetic expansion in the shell. Bash-1.14... lists both forms of arithmetic expansion, but by the time bash-2.0 was released in 1995, the manual referred only to the $((...)) form.
这向我表明 $[]
形式是 实验性的 ,并且它有某些行为(如大括号扩展)在 [=38= 时被指定为遗忘] 采用了 $(())
语法。那些实验性的行为被保留了下来,因为已经有脚本在野外依赖它们(记住已经过去了 2 年多)。
Chet 在同一主题中明确表示 $[]
表格已过时,但并未弃用:
Now, it's hardly any problem to keep dragging the $[...] syntax along. It takes only a few dozen bytes of code. I have no plans to remove it.
current POSIX standard, C.2.6 Word Expansions > Arithmetic Expansion 提到语法(强调我的):
In early proposals, a form $[expression] was used. It was functionally equivalent to the "$(())" of the current text, but objections were lodged that the 1988 KornShell had already implemented "$(())" and there was no compelling reason to invent yet another syntax. Furthermore, the "$[]" syntax had a minor incompatibility involving the patterns in case statements.
因此 bash 中的实施行为并不完全符合规范,但由于没有删除它的计划,如果它巧妙地解决了您的问题,我认为没有理由放弃它的好处。但是,正如@Barmar 的评论所指出的那样,在此处对代码进行注释并 link 是个好主意,这样未来的开发人员就知道您到底是什么意思了!
printf %4d $(({1..10}*i))
由于参数在 bash
中展开的顺序而不起作用。大括号展开 ({}
) 比算术展开 ($(())
) 早 bash
。如果是其他方式,您的代码肯定会工作。
来自man bash
:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.
运行 像这样 bash。这个问题要求解释,而不是解决方案,但这里将是一种 $(()) 表达方式。
for i in {1..10}; do
printf %4d $(eval echo '$(('{1..10}'*i))')
echo
done
像参数扩展一样,在算术扩展中禁止大括号扩展。
(bash 手动)
To avoid conflicts with parameter expansion, the string ‘${’ is not considered eligible for brace expansion, and inhibits brace expansion until the closing ‘}’.