跳轉到

2009:Bash 4.0——關聯陣列與萬用字元強化#

事件#

2009 年 2 月,Bash 4.0 問世(由 Chet Ramey 維護)。這是 bash 語法表達力最大的一次擴充,補上了資料結構與檔名展開的兩大長期缺口。

新語法與特性及其理論、實用原因#

1. 關聯陣列(declare -A map)#

  • 理論原因:鍵值對(key-value pair)是最常用的資料抽象,ksh93 早在 1993 年就有。
  • 實用原因:map[key]=value 直接做查找表,不需靠「字串拼接 + grep」模擬。
  • 彌補缺陷:bash 2.0 只有索引陣列,鍵值查找必須用兩個平行陣列或外部程式(awk)。

2. 遞迴萬用字元 **(需 shopt -s globstar)#

  • 理論原因:檔名展開是 shell 的核心運算,zsh(1990)早已支援遞迴 glob。
  • 實用原因:ls **/*.c 遞迴列出所有 C 檔,不需 find . -name。
  • 彌補缺陷:bash 的 * 只匹配單層目錄,遞迴必須依賴外部 find。

3. &>>、|& 等重導向簡寫#

  • 實用原因:cmd &>> file 同時重導向 stdout/stderr 並附加;|& 把 stderr 也送進管線。
  • 彌補缺陷:cmd >> file 2>&1 語序易錯(2>&1 放錯位置是經典 bug);ksh 的 coprocess 語法於此跟進。

4. coproc 雙向管線#

  • 理論原因:管線只有單向流(1973 年的設計),長駐行程無法互動。
  • 實用原因:腳本可與背景行程雙向溝通(如互動式資料庫)。
  • 彌補缺陷:ksh93 早在 1988 年就有 |&,bash 補上。

5. ${var,,}、${var^^} 大小寫轉換與 declare -l/-u#

  • 實用原因:大小寫轉換不需 fork tr。

程式範例:Bash 4.0 的新語法#

# 1. 關聯陣列:鍵值查找表(ksh93 早在 1993 就有)
declare -A ver
ver[bash]=3.2
ver[zsh]=5.9
echo "${ver[bash]}"          # 3.2
echo "${!ver[@]}"            # bash zsh(所有鍵)

# 對比:以前要靠兩個平行陣列或 awk 模擬
# 2. 遞迴 glob(globstar)
shopt -s globstar
ls **/*.c                    # 遞迴列出所有 C 檔——不需 find
rm **/*.o

# 對比:以前的寫法
# find . -name '*.c' -exec ls {} \;
# 3. 重導向簡寫
prog &>> log.txt             # stdout+stderr 附加到檔案
# 對比:cmd >> log.txt 2>&1——語序易錯(2>&1 放錯位置是經典 bug)

prog |& grep ERROR           # stderr 也送進管線
# 對比:prog 2>&1 | grep ERROR
# 4. coproc:雙向管線
coproc SQLITE { sqlite3 test.db; }
echo "SELECT 1;" >&"${SQLITE[1]}"    # 送命令
read line <&"${SQLITE[0]}"           # 讀結果
# 5. 大小寫轉換:不需 fork tr
s="Hello World"
echo "${s,,}"                # hello world
echo "${s^^}"                # HELLO WORLD

歷史意義#

Bash 4.0 讓 bash 的資料結構(索引陣列 + 關聯陣列)與檔名展開(globstar)追上 zsh/ksh93,確立了「bash 腳本」超越「POSIX 腳本」的表達力優勢。之後 2016 年 bash 4.4(-v 變數追蹤)、2019 年 bash 5.0(EPOCHSECONDS)持續小步擴充。

彌補了什麼缺陷#

彌補了 bash「無關聯陣列、glob 不遞迴、管線單向」的表達力缺陷,大幅減少對外部程式(find、awk、tr)的依賴。

相關條目#