Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux Shell 序列與陣列高效生成技巧:brace expansion、seq、mapfile 實戰對比

編輯:Linux 教學

在 Shell 腳本中生成數字序列、字串列表、陣列是基礎且高頻的操作。本文深度對比 Brace Expansion {start..end..step}、外部命令 seq、內建 mapfile/readarray、迴圈累加 四大生成方式的效能、功能差異與適用場景,並提供陣列操作進階技巧 (切片、關聯陣列、稀疏陣列)。

一、序列生成四大方式對比

方式語法範例產出類型效能 (10萬項)功能特色
Brace Expansion{1..100000} / {a..z} / {01..10}字串列表 (IFS 分隔)~5ms (最快)純內建、支援字母、前導零、步進 {1..100..2}
seq 命令seq 1 100000 / seq -f "%03g" 1 100標準輸出 (需命令替換)~45ms格式化豐富、浮點數、分隔字串自訂
for 迴圈累加for((i=1;i<=100000;i++)); do arr+=($i); done直接建立陣列~120ms邏輯最靈活、可嵌入複雜條件
mapfile/readarraymapfile -t arr < <(seq 100000)直接建立陣列~30ms高效讀取輸入流建立陣列、支援回呼

二、字串列表 vs 陣列:核心差異


# 字串列表 (以空白/IFS 分隔)
str_list=$(seq 5)          # "1 2 3 4 5"
for i in $str_list; do     # 依賴 IFS 分詞,遇含空白元素會錯誤
    echo $i
done

# 索引陣列
arr=($(seq 5))             # (1 2 3 4 5)
echo ${arr[2]}             # 3 (索引從 0 開始)
echo ${#arr[@]}            # 5 (長度)
for i in "${arr[@]}"; do   # 正確遍歷,保留元素內空白
    echo $i
done

# 關聯陣列 (Bash 4+)
declare -A assoc
assoc=([id]=100 [name]="test" [enable]=true)
echo ${assoc[name]}        # test

三、Brace Expansion 進階用法


# 數字範圍 (支援前導零、遞減、步進)
echo {1..10}           # 1 2 3 4 5 6 7 8 9 10
echo {10..1}           # 10 9 8 7 6 5 4 3 2 1
echo {01..10}          # 01 02 03 04 05 06 07 08 09 10
echo {1..10..2}        # 1 3 5 7 9 (Bash 4+)

# 字母範圍
echo {a..f}            # a b c d e f
echo {A..C}            # A B C
echo {z..a}            # z y x w v u t s r q p o n m l k j i h g f e d c b a

# 組合展開 (笛卡兒積)
echo {a,b,c}{1,2,3}    # a1 a2 a3 b1 b2 b3 c1 c2 c3
echo pre_{1..3}_suf    # pre_1_suf pre_2_suf pre_3_suf

# 巢狀展開 (需 eval 或迴圈)
# eval echo {{1..3},{a..c}}  # 1 2 3 a b c

四、seq 格式化輸出實戰


# 固定寬度前導零
seq -f "%04g" 1 20       # 0001 0002 ... 0020
seq -w 1 20              # 自動寬度 (等同 %02g)

# 自訂分隔字串
seq -s "," 1 5           # 1,2,3,4,5
seq -s $'\n' 1 5         # 換行分隔 (適合管道)

# 浮點數步進
seq 0 0.5 2              # 0 0.5 1.0 1.5 2.0

五、陣列進階操作技巧

1. 切片與子陣列


arr=(a b c d e f g)
echo ${arr[@]:2:3}       # c d e (索引 2 起長度 3)
echo ${arr[@]: -3}       # e f g (倒數 3 個)

2. 陣列合併與去重


arr1=(1 2 3)
arr2=(3 4 5)
merged=("${arr1[@]}" "${arr2[@]}")   # 1 2 3 3 4 5

# 去重 (需排序)
unique=($(printf "%s\n" "${merged[@]}" | sort -u))  # 1 2 3 4 5

3. 稀疏陣列 (索引不連續)


sparse=([10]=a [20]=b [30]=c)
echo ${#sparse[@]}       # 3
echo ${!sparse[@]}       # 10 20 30 (所有索引)
echo ${sparse[15]:-N/A}  # N/A (預設值)

4. 關聯陣列遍歷排序


declare -A scores=([alice]=95 [bob]=87 [charlie]=92)
for name in "${!scores[@]}"; do
    echo "$name: ${scores[$name]}"
done | sort -k2 -nr   # 依分數降序

六、效能基準測試腳本 (可直接執行)


#!/bin/bash
# bench_array_gen.sh
N=100000

echo "=== Brace Expansion ==="
time bash -c "arr=({1..$N}); echo \${#arr[@]}"

echo "=== seq + command substitution ==="
time bash -c "arr=(\$(seq $N)); echo \${#arr[@]}"

echo "=== mapfile + seq ==="
time bash -c "mapfile -t arr < <(seq $N); echo \${#arr[@]}"

echo "=== for loop ==="
time bash -c "arr=(); for((i=1;i<=N;i++)); do arr+=(\$i); done; echo \${#arr[@]}"

# 典型輸出 (Intel i7-1165G7, Bash 5.1)
=== Brace Expansion ===
arr=({1..100000}); echo ${#arr[@]}
real    0m0.012s
=== seq + command substitution ===
arr=($(seq 100000)); echo ${#arr[@]}
real    0m0.058s
=== mapfile + seq ===
mapfile -t arr < <(seq 100000); echo ${#arr[@]}
real    0m0.035s
=== for loop ===
arr=(); for((i=1;i<=100000;i++)); do arr+=($i); done; echo ${#arr[@]}
real    0m0.142s

七、最佳實踐建議

  1. 純整數序列、前導零、字母序列 → Brace Expansion (最快、最簡潔、純內建)
  2. 浮點數、自訂格式化、複雜分隔字串 → seq
  3. 直接建立陣列、需處理大量輸入流 → mapfile/readarray
  4. 邏輯複雜、條件生成、非線性序列 → for/while 迴圈
  5. 避免 arr=($(cmd)) 在極大輸出 (超過百萬行) 時記憶體飆升,改用 mapfile 或串流處理。

熟練掌握序列與陣列生成的多種工具箱,能在 Shell 腳本中以最少代碼、最高效能完成資料準備、批次處理、測試資料構建等高頻任務。

Copyright © Windows教程網 All Rights Reserved