awk 陣列為關聯陣列,for (k in arr) 遍歷順序不確定。本文詳解四種排序輸出方案,含效能分析與適用場景建議。
awk 'BEGIN{info="this is a test"; split(info,a," "); for(k in a) print k,a[k]}'
# 輸出順序不定:4 test / 1 this / 2 is / 3 a
awk 'BEGIN{info="this is a test"; n=split(info,a," "); for(i=1;i<=n;i++) print i,a[i]}'
# 輸出:1 this / 2 is / 3 a / 4 test
限制:索引必須為 1..n 連續整數。
awk 'BEGIN{a[100]=100; a[2]=224; a[3]=34; n=asort(a,b); for(i=1;i<=n;i++) print i,b[i]}'
# 輸出:1 34 / 2 100 / 3 224 (原鍵值 100/2/3 遺失)
awk 'BEGIN{a["d"]=100; a["a"]=224; a["c"]=34; n=asorti(a,b); for(i=1;i<=n;i++) print i,b[i],a[b[i]]}'
# 輸出:1 a 224 / 2 c 34 / 3 d 100 (按鍵字典序)
注意:asort/asorti 僅支援 gawk (GNU awk),mawk/nawk 不支援。
awk 'BEGIN{a[100]=100; a[2]=224; a[3]=34; for(i in a) print i,a[i] | "sort -rn -k2"}'
# 輸出:2 224 / 100 100 / 3 34
awk 'BEGIN{a[100]=100; a[2]=224; a[3]=34; for(i in a) print i,a[i] | "sort -rn -k1"}'
# 輸出:100 100 / 3 34 / 2 224
awk 'BEGIN{a["d"]=100; a["a"]=224; a["c"]=34; for(i in a) print i,a[i] | "sort -k1"}'
# 輸出:a 224 / c 34 / d 100
優點:利用系統 sort 高效能、支援海量資料、語法簡潔。
缺點:啟動子進程、需格式化輸出供 sort 解析。
function sortArr(arr, key, datatype, tarr, splitseq, alen, k, m, n, tm, tn, tnum) {
if (key !~ /^[12]$/) return 0
splitseq = "%%"
for (k in arr) tarr[++alen] = k splitseq arr[k]
for (m=1; m<=alen; m++) {
for (n=1; n<=alen-m; n++) {
split(tarr[m], tm, splitseq)
split(tarr[n+1], tn, splitseq)
if (datatype == 1) { # 數值比較
if (tm[key]+0 < tn[key]+0) { tnum=tarr[m]; tarr[m]=tarr[n+1]; tarr[n+1]=tnum }
} else { # 字串比較
if (tm[key] "" < tn[key] "") { tnum=tarr[m]; tarr[m]=tarr[n+1]; tarr[n+1]=tnum }
}
}
}
return alen
}
# 使用範例:按鍵字典序降序
awk 'BEGIN{
a["a"]=100; a["b"]=110; a["c"]=10
n=sortArr(a, 2, 2) # key=2(值), datatype=2(字串)
for(i=1;i<=n;i++) { split(tarr[i],ta,"%%"); print i,ta[1],ta[2] }
}'
# 輸出:1 b 110 / 2 a 100 / 3 c 10
| 方法 | 適用資料量 | 相依性 | 鍵值保留 | 速度 |
|---|---|---|---|---|
| 索引遍歷 | 小、連續索引 | 無 | 完整 | 最快 |
| asort/asorti | 中、需 gawk | gawk 3.1+ | asorti 保留 | 快 |
| 管線 sort | 大、跨平台 | 系統 sort | 完整 | 中 (進程開銷) |
| 自定義函數 | 小、無外部依賴 | 無 | 完整 | 中 (O(n²)) |
實務上:<1萬筆用 asorti/管線 sort,>10萬筆必用管線 sort,嵌入式無 sort 指令才寫自定義函數。