expr
似乎不喜欢括号(在数学中用于明确的运算符优先级):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
如何在bash中表达操作员优先级?
expr
似乎不喜欢括号(在数学中用于明确的运算符优先级):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
如何在bash中表达操作员优先级?
Answers:
使用let
bash内置的另一种方法:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
注意
正如@StéphaneChazelas所指出的那样,bash
您应该使用((...))
来做算术运算expr
或let
使其易于辨认。
对于可移植性,请使用$((...))
类似@Bernhard answer的方法。
let
。它的标准性或可移植性都没有(( a = 3 * (2 + 1) ))
(两者都来自ksh
,并且仅在ksh,bash和zsh中可用),并且可读性或引用性较差。用于a=$((3 * (2 + 1)))
便携式。
((a = 3 * (2 + 1) ))
,一种代表便携性a=$((3 * (2 + 1)))
),因此它不是针对您或您的答案的注释,而是针对它作为选定的答案和得分最高的球员。
a=1 $[a+2]
或a=1 b=2 $[a+b]
。他们有理由避免使用这种语法吗?
您可以改用算术扩展。
echo "$(( 3 * ( 2 + 1 ) ))"
9
我个人认为,这比使用更好expr
。
从 man bash
算术扩展 算术扩展允许评估算术表达式和替换结果。算术扩展的格式为:
$((expression))
将该表达式视为在双引号内,但括号内的双引号未得到特殊处理。表达式中的所有标记都经过参数扩展,字符串扩展,命令替换和引用删除。算术扩展可以嵌套。
根据以下“算术评估”下列出的规则进行评估。如果表达式无效,则bash会显示一条指示失败的消息,并且不会发生替换。
没有理由expr
在现代shell中使用算术。
POSIX定义$((...))
扩展运算符。因此,您可以在所有POSIX兼容外壳程序(sh
所有现代Unix-like,dash,bash,yash,mksh,zsh,posh,ksh等)中使用它。
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
还引入了一个let
内建函数,该内函数传递了相同的算术表达式,它不会扩展为某种东西,而是根据表达式是否解析为0来返回退出状态,例如expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
但是,由于报价不方便且不清晰(expr
当然程度不同),因此ksh
还引入了((...))
另一种形式:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
这更容易理解,应该改为使用。
let
并且((...))
是只适用于ksh
,zsh
和bash
。的$((...))
语法应首选如果需要移植到其他外壳,expr
只需要换POSIX预类似Bourne壳(典型的是Bourne壳或壳Almquist的早期版本)。
在非伯恩前端,有一些带有内置算术运算符的shell:
csh
/ tcsh
(实际上是第一个内置有算术评估的Unix shell):
@ a = 3 * (2 + 1)
akanga
(基于rc
)
a = $:'3 * (2 + 1)'
作为历史记录,1989年在usenet上发布的Almquist shell的原始版本具有expr
内置功能(实际上与合并test
),但后来被删除了。
: $((a = a*2))
样
$((...))
zsh,ksh93或yash之类浮点数的shell 。
expr
是外部命令,不是特殊的shell语法。因此,如果要expr
查看shell特殊字符,则需要通过引用它们来保护它们免受shell解析。此外,expr
需要将每个数字和运算符作为单独的参数传递。从而:
expr 3 \* \( 2 + 1 \)
除非您正在研究1970或1980年代的老式Unix系统,否则几乎没有理由使用expr
。在过去,shell没有内置的算法来执行算术,而您必须调用该expr
实用程序。所有POSIX Shell都通过算术扩展语法具有内置算术。
echo "$((3 * (2 + 1)))"
该构造$((…))
扩展为算术表达式的结果(以十进制表示)。击,最喜欢的壳,仅支持整数运算模2 64(或模2 32对旧版本的bash和在32位机器一些其他shell)。
当您要执行赋值或测试表达式是否为0但不关心结果时,Bash提供了一种额外的便捷语法。此构造也存在于ksh和zsh中,但不存在于纯sh中。
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
除整数算术外,expr
还提供一些字符串操作函数。POSIX shell的功能也包含这些内容,但以下一项除外:expr STRING : REGEXP
测试字符串是否与指定的regexp相匹配。没有外部工具,POSIX shell无法做到这一点,但是bash可以[[ STRING =~ REGEXP ]]
(使用不同的regexp语法 -这 expr
是一个经典工具,并且使用BRE,bash使用ERE)。
除非您要维护在具有20年历史的系统上运行的脚本,否则您无需知道该脚本expr
是否存在。使用壳算术。
expr foo : '\(.\)'
也可以提取文字。bash
的效果BASH_REMATCH
类似。它还可以进行字符串比较,而POSIX [
则不这样做(尽管可以想象使用sort
它的方式)。