Shell 腳本原生支援多種進制字面值表示與算術運算,無需呼叫外部工具即可完成進制轉換。本文系統整理 Bash/Zsh 內建語法、bc 計算器進階用法、printf 格式化輸出、Base64 編碼/解碼、位元運算技巧,並提供可直接引用的函數庫片段。
| 進制 | 前綴/語法 | 範例 | 說明 |
|---|---|---|---|
| 二進制 | 2# | 2#1010 (=10) | Bash/Zsh 支援 base#number,base 2~64 |
| 八進制 | 0 或 8# | 012 / 8#12 (=10) | 0 前綴為 POSIX 標準 |
| 十進制 | (無前綴) | 10 | 預設 |
| 十六進制 | 0x 或 16# | 0xA / 16#A (=10) | 0x 為 C 風格標準 |
| Base64 | 64# | 64#A_ (=64) | 字符集 A-Z a-z 0-9 @ _ (Bash 定義) |
$((...)))
# 直接賦值 (算術語境自動轉換)
dec=$((2#1010)) # 10
dec=$((8#12)) # 10
dec=$((16#FF)) # 255
dec=$((64#A_)) # 64
# 變數插值
bin="1010"
dec=$((2#$bin)) # 10
# let 命令同樣支援
let "dec = 16#FF"
echo $dec # 255
# obase 指定輸出進制
echo "obase=2; 255" | bc # 11111111
echo "obase=8; 255" | bc # 377
echo "obase=16; 255" | bc # FF
echo "obase=64; 255" | bc # 3V (bc 使用 0-9 A-Z 字符集,非標準 Base64)
# 互動模式
bc <<< "obase=16; ibase=2; 11111111" # FF (ibase 指定輸入進制)
printf "%o\n" 255 # 377 (八進制)
printf "%d\n" 255 # 255 (十進制)
printf "%x\n" 255 # ff (十六進制小寫)
printf "%X\n" 255 # FF (十六進制大寫)
printf "%#x\n" 255 # 0xff (帶前綴)
Shell 內建 64# 使用非標準字符集,**不可用於標準 Base64 互操作**。請使用 base64 指令:
# 編碼
echo -n "Hello" | base64 # SGVsbG8=
printf "Hello" | base64 -w0 # 無換行
# 解碼
echo "SGVsbG8=" | base64 -d # Hello
base64 -d <<< "SGVsbG8=" # Hello
# 檔案編碼
base64 -w0 input.bin > output.b64
base64 -d output.b64 > output.bin
# convert_base.sh
# 用法: convert_base <輸入進制> <輸出進制> <數值>
# 支援 2~36 進制 (受限於 bc/printf)
convert_base() {
local in_base=$1 out_base=$2 value=$3
local dec
# 1. 輸入 → 十進制
case $in_base in
2|8|10|16) dec=$((in_base#$value)) ;;
*) dec=$(bc <<< "ibase=$in_base; $value") ;;
esac
# 2. 十進制 → 輸出
case $out_base in
2) echo "obase=2; $dec" | bc ;;
8) printf "%o\n" $dec ;;
10) echo $dec ;;
16) printf "%X\n" $dec ;;
*) echo "obase=$out_base; $dec" | bc ;;
esac
}
# 範例
# source convert_base.sh
# convert_base 16 2 FF → 11111111
# convert_base 2 16 11111111 → FF
# convert_base 10 64 4096 → 100 (bc 字符集)
# 判斷奇偶
(( n & 1 )) && echo "odd" || echo "even"
# 乘除 2 的冪次 (位移)
(( n << 3 )) # n * 8
(( n >> 2 )) # n / 4
# 清除最低位的 1 (n & (n-1))
# 用於判斷 2 的冪次:(( n & (n-1) )) == 0
# 取模 2^n (位元遮罩)
(( n % 16 )) 等價於 (( n & 15 ))
# 交換兩變數 (無暫存變數)
(( a ^= b, b ^= a, a ^= b ))
| 坑點 | 錯誤示範 | 正確做法 |
|---|---|---|
| 前導零被視為八進制 | num=012; echo $num 輸出 012 (字串) | num=012; echo $((num)) 或 num=$((8#12)) |
| Base64 字符集差異 | 混淆 Bash 64# 與標準 base64 | 標準編解碼務必用 base64 指令 |
| bc 輸出大寫字母 | echo "obase=16; 255" | bc 輸出 FF | 若需小寫:... | tr 'A-Z' 'a-z' |
| 極大數值溢位 | Bash 整數 64 位有號 (-2^63~2^63-1) | 超出範圍改用 bc、python -c、gawk |
掌握 Shell 內建進制語法、bc/printf 格式化、標準 base64 指令與位元運算技巧,即可在腳本中高效完成各類進制轉換、位元旗標操作、權限模式計算 (chmod 數值)、網路位址運算等底層任務,無需依賴外部腳本語言。