2010-03-25 95 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等也是如此。