BASH算术表达式

时间:2010-03-25 17:07:50

标签: bash floating-point math expression

我在BASH(3.2)中使用了几种方法来做一些简单的整数运算。但我无法找出最好的(首选)方法。

result=`expr 1 + 2`
result=$(( 1 + 2 ))
let "result = 1 + 2"

这些表达方式之间的根本区别是什么? 还有其他方法可以做同样的事吗?

对于浮点运算,是否必须使用像bc这样的工具?

result=`echo "7/354" | bc`

5 个答案:

答案 0 :(得分:17)

在Bash中,let允许在一行上进行多次分配:

let a=3 b=4 c=5

正如您在问题中所示,引用let的参数可以让您在运算符周围添加空格。但是,如果避免使用空格,则可以省略引号。

在语句开头使用双括号的另一种形式(而不是i=$((j + 1))形式)允许您在等号周围包含空格,或者进行后增量或预增量或减量以及其他赋值操作: / p>

(( a = ( b + c ) * 4 ))
(( count++ ))
(( d = --c**2 ))
(( e *= 2 ))
(( f = 3, g = 5 ))    # multiple operations require a comma separator

如果您执行help "((",则表示双括号“等效于”let EXPRESSION“。”

您可以使用declare内置来进行分配,包括间接分配:

blue=2
name=blue
declare $name=4
echo $blue    # result: 4
echo ${!name} # result: 4

修改

$(())构造称为“arithmetic expansion”,并将内容作为整数表达式进行求值。它是shell的语法元素。

如果变量声明为整数,则不需要使用任何形式的双括号,可以省略变量名称中的美元符号(如双括号表单中所示),但不能添加运营商周围的空间:

declare -i x=1   # set integer, initialize to 1
declare +i s=1   # clear integer, initialize to 1
x+=1             # could also be x=x+1
echo $x          # result: 2 (addition)
s+=1             # could also be s=$s+1, requires a "$"
echo $s          # result: 11 (string concatenation)

与上面的表单不同,调用expr涉及产生一个外部可执行文件,这对于循环中的大量计算来说可能非常昂贵。应该使用的时间是在shell无法进行自己的算术运算或者脚本可能进入这样的环境时可移植性的环境中。 POSIX shell具有算术功能,因此只关注旧系统。

关于使用bc进行浮点运算,在使用Bash和许多其他shell时需要它或类似的东西。 POSIX说“只需要签名的长整数运算。”

支持float数学的两个shell是ksh和zsh。除了bc之外,您还可以在Bash脚本中使用dc,AWK,Python,Perl等。

Bash 使用浮点数做的一件事是使用内置printf打印它们(请注意,还有一个外部printf,但内置优先级)

printf "%'14.4f\n" 1234.56  # result "    1,234.5600" (in my locale)

答案 1 :(得分:5)

我更喜欢你的第二种选择,因为它不需要外部工具:

result=$(( 1 + 2 ))

第一个选项呼叫expr进行数学运算 - 我不熟悉letbc的另一种替代方法是dc。选择你最喜欢的。

答案 2 :(得分:4)

我不能说它是“强制性的”,但bc可能是通用算术的最佳选择。

对于更高档的东西,你总是可以穿越Perl。

这两种方法的缺点是它们都打开子进程,因此在紧密循环中执行它将比本机bash表达式慢(在第一个示例中使用反引号会出现同样的问题)。我不确定$(())是否会调用子进程。

答案 3 :(得分:3)

Is the use of a tool like bc mandatory for floating point arithmetic?

不,如果您使用支持浮点的shell,例如zsh,ksh。否则,如果要进行更高级的浮点数学运算,请使用其中一个bc/awk/dc。当然,还有Perl / Python等。

答案 4 :(得分:0)

您拥有的第三个选项可读性较差,因为它看起来不像赋值运算符。第一个,如其他人所指出的,调用外部命令