2010-03-25 87 views
18

我曾经用过几种方法在BASH(3.2)中做了一些简单的整数运算。但我无法弄清楚最好的(首选)方法。BASH算术表达式

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

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

浮点算术是否必须使用像bc这样的工具?

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

回答

17

在bash,let允许在一条线上的多个作业:

let a=3 b=4 c=5 

当你表现出你的问题,引用的参数let允许你把运营商周围的空间。但是,如果避免使用空格,则可以省略引号。

使用双括号在声明(而非i=$((j + 1))形式)开始另一种形式允许包括等号周围空间或做后或预递增或递减的和额外的赋值操作:

((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外壳具有算术能力,因此只有在较老的系统中才会考虑它。

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

确实支持浮点运算的两个shell是ksh和zsh。除了bc之外,您还可以在Bash脚本中使用dc,AWK,Python,Perl和其他程序。

一两件事,猛砸做浮点数与printf内置(注意,也有外部printf,但是内建有优先权)打印出来。

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

你没有讨论产生'expr'等等的含义以及'$(())'是否是bultin。 – vladr 2010-03-26 03:57:10

+0

@Vlad:我希望你能找到一些改进。 – 2010-03-26 05:14:15

+0

谢谢你的补充。 :) +1 – vladr 2010-03-26 07:03:12

4

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

对于更奇特的东西,你总是可以通过Perl来管道。

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

5

我喜欢你的第二个选项,因为它并不需要一个外部工具:

result=$((1 + 2)) 

第一个选项叫一声expr做数学题 - 我不熟悉letbc的另一种替代方法是dc。选择你最喜欢的。

0

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

3

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

没有,如果你正在使用支持浮点外壳,如的zsh和ksh。否则,如果您想要执行更高级的浮点数学运算,请使用其中之一,bc/awk/dc。当然,Perl/Python等也是如此。