Shell 中的整數運算與浮點數處理 文章首圖

Shell 中的整數運算與浮點數處理

Shell 中的整數運算與浮點數處理

在 Linux 系統管理與自動化腳本開發中,運算能力是不可或缺的核心功能。許多初學者常會遇到一個經典問題:為什麼在 Bash 中直接輸入 echo $((1 + 1)) 可以運作,但 echo 1 + 1 卻只是輸出字串?更令人困擾的是,當我們需要處理網路頻寬、檔案大小或精度要求較高的數值時,Bash 原生並不支援浮點數運算,導致許多腳本邏輯無法直接實現。

這篇文章將深入探討 Bash 中的整數運算機制,並介紹如何透過外部工具輕鬆處理浮點數,讓你的腳本更具彈性與實用性。

Bash 原生整數運算

Bash 是一個基於字串的解釋型語言,其內建的運算能力僅限於整數。若嘗試對浮點數進行運算,Bash 會直接報錯。我們主要有三種方式在 Bash 中進行整數運算。

1. 雙括號運算 $((...))

這是最推薦且最標準的寫法。雙括號內的內容會被視為算術擴展(Arithmetic Expansion),支援加減乘除、取餘數、指數運算等。

#!/bin/bash

# 定義變數
a=10
b=3

# 基本運算
echo "a + b = $((a + b))"   # 輸出 13
echo "a - b = $((a - b))"   # 輸出 7
echo "a * b = $((a * b))"   # 輸出 30
echo "a / b = $((a / b))"   # 輸出 3 (注意:這是整數除法,小數部分被捨去)
echo "a % b = $((a % b))"   # 輸出 1 (取餘數)

# 指數運算 (2 的 10 次方)
echo "2^10 = $((2**10))"    # 輸出 1024

2. let 命令

let 是 Bash 內建的命令,用於執行算術運算。它通常用於賦值,語法較為簡潔,但可讀性略低於 $((...))

let x=5+5
echo "x = $x"   # 輸出 10

# 注意:let 後面若有多個運算,建議用空格分隔或使用雙引號
let "y = 10 / 3"
echo "y = $y"   # 輸出 3

3. expr 命令

expr 是一個外部命令(External Command),而非 Bash 內建。它較舊且效能稍差,但在某些極簡環境或 POSIX 相容性要求高的場景中仍會見到。使用時需注意運算子與數字間必須有空格,且乘法符號需跳脫。

# 必須有空格,否則會報錯
result=$(expr 10 + 5)
echo "result = $result"   # 輸出 15

# 乘法需要跳脫符號 \
result=$(expr 10 \* 5)
echo "result = $result"   # 輸出 50

突破限制:浮點數處理

既然 Bash 不支援浮點數,我們必須依賴外部工具。在 Ubuntu 22.04 / Debian 12 中,最強大且常用的工具是 awkbc

方法一:使用 awk 進行浮點運算

awk 不僅擅長處理文本,其內建的數學引擎也能完美處理浮點數。它的語法與 C 語言類似,非常直觀。

#!/bin/bash

# 計算圓周面積:pi * r^2,假設 pi=3.14159, r=5
r=5
pi=3.14159

# awk 的輸出格式控制:%.2f 表示保留兩位小數
area=$(awk "BEGIN {printf \"%.2f\", $pi * $r * $r}")
echo "圓周面積: $area"   # 輸出 78.54

# 浮點數除法
result=$(awk "BEGIN {printf \"%.4f\", 10 / 3}")
echo "10/3 的結果: $result"   # 輸出 3.3333

方法二:使用 bc (Basic Calculator)

bc 是專門用於數學運算的指令列工具,支援任意精度。對於需要極高精度的科學計算,bc 是首選。

#!/bin/bash

# 安裝 bc (若尚未安裝)
# sudo apt install bc

# 基本浮點運算
echo "scale=4; 10 / 3" | bc
# 輸出 3.3333

# 指數運算
echo "2^10" | bc
# 輸出 1024

# 更複雜的表達式
result=$(echo "scale=2; (3.14 * 5 * 5)" | bc)
echo "圓周面積 (bc): $result"   # 輸出 78.50

常見問題與解決方案

Q1: 為什麼 echo $((1.5 + 1.5)) 會報錯?

解答: Bash 的算術擴展 $((...)) 嚴格限制為整數運算。當它遇到小數點時,會將其視為無效字元或截斷小數部分(取決於版本),進而導致語法錯誤。

解決: 若需處理小數,請務必使用 awkbc。例如:awk "BEGIN {print 1.5 + 1.5}"

Q2: 腳本中變數內容包含空格或特殊字元,運算失敗怎麼辦?

解答: 在傳遞變數給 awkbc 時,若變數值包含空格,會破壞命令的結構。

解決: 使用 -v 參數(針對 awk)將變數安全傳入,或確保變數被正確引用。

# 錯誤示範:若 name="10 20",則 awk 會誤判
value="10 20"
awk "BEGIN {print $value + 5}" 

# 正確示範:使用 awk 的 -v 參數
val=10
awk -v v="$val" 'BEGIN {print v + 5}'

小結

在 Linux Shell 腳本中,整數運算應優先使用 $((...)),因其效能最高且語法標準。而當需求擴展至浮點數或高精度計算時,awk 提供了便捷的格式控制,bc 則提供了強大的任意精度支援。掌握這兩種工具的搭配使用,將大幅提升你撰寫系統管理腳本的專業度與可靠性。下次當你需要計算檔案壓縮率或網路延遲平均值時,別再讓 Bash 的整數限制絆住你的腳步了!