人人都会AI编程

14.3 数组与字符串处理

更新时间:2026-07-12

在 Shell 脚本里,数组和字符串是数据处理的基础。Bash 提供了一维数组,支持整数索引和关联数组;而字符串操作则大量依赖变量扩展和外部工具。掌握这些基本技巧,可以让你轻松处理配置解析、日志字段拆分、批量文件重命名等日常任务。

1. 普通索引数组
定义数组时,用圆括号把元素括起来,元素之间用空格分隔:

fruits=(apple banana cherry)

也可以逐个赋值:

fruits[0]=apple
fruits[1]=banana
fruits[3]=durian          # 索引可以不连续

读取某个元素使用 ${数组名[索引]},读取所有元素使用 ${数组名[@]}${数组名[*]}

echo ${fruits[1]}          # banana
echo ${fruits[@]}          # apple banana cherry durian

获取数组长度(元素个数):

echo ${#fruits[@]}         # 4

遍历数组最常用的写法是:

for item in "${fruits[@]}"; do
    echo "水果: $item"
done

注意:用双引号括起 ${fruits[@]} 可以正确处理包含空格的元素。

2. 关联数组(类似字典)
Bash 4.0 以上支持关联数组,使用字符串作为键。声明时必须用 declare -A

declare -A user
user[name]="张三"
user[age]=25
user[city]="北京"

读取时和索引数组类似:

echo ${user[name]}          # 张三
echo ${!user[@]}            # 列出所有键:name age city
echo ${#user[@]}            # 元素数量:3

遍历所有键值对:

for key in "${!user[@]}"; do
    echo "$key = ${user[$key]}"
done

3. 字符串基本操作
字符串变量可以直接通过花括号扩展执行多种操作,无需调用外部命令,效率很高。

  • 获取字符串长度:
str="hello world"
echo ${#str}                # 11
  • 截取子串:
echo ${str:0:5}             # hello  (从索引0开始取5个字符)
echo ${str:6}               # world  (从索引6开始到末尾)
  • 删除前缀/后缀:
path="/usr/local/bin/script.sh"
echo ${path#*/}             # usr/local/bin/script.sh  (最短匹配删除从头到第一个/)
echo ${path##*/}            # script.sh                 (最长匹配删除从头到最后一个/)
echo ${path%/*}             # /usr/local/bin            (最短匹配删除从尾到第一个/)
echo ${path%%/*}            # 空字符串                   (最长匹配删除从尾到最后一个/)
  • 替换子串:
text="apple banana apple"
echo ${text/apple/orange}   # orange banana apple   (替换第一个)
echo ${text//apple/orange}  # orange banana orange  (替换所有)
echo ${text/#apple/pear}    # pear banana apple     (匹配开头替换)
echo ${text/%apple/pear}    # apple banana pear     (匹配结尾替换)

4. 字符串处理的实用组合

  • 批量重命名文件(结合 for 循环和变量替换):
for file in *.txt; do
    mv "$file" "${file/.txt/.md}"
done

.txt 后缀替换为 .md

  • 切割字符串:使用 read 命令配合 IFS 分隔符:
line="张三:25:北京"
IFS=":" read -r name age city <<< "$line"
echo "$name 今年 $age 岁,来自 $city"
  • 使用 trsed 处理更复杂的文本
echo "Hello World" | tr '[:upper:]' '[:lower:]'   # 转小写
echo "a,b,c" | sed 's/,/\n/g'                     # 逗号换行

5. 数组与字符串结合的常见场景

  • 将命令输出存入数组(按行分割):
mapfile -t lines < access.log   # 将文件每一行作为数组元素
echo "日志共 ${#lines[@]} 行"
  • 将字符串按分隔符拆分为数组:
csv="red,green,blue"
IFS="," read -ra colors <<< "$csv"
echo ${colors[1]}             # green

小结
Shell 的数组可以方便地管理列表和键值对,字符串扩展则提供了轻量级的文本处理能力。在实际脚本中,尽量优先使用内建操作(如 ${var#pattern}${var//old/new}),它们比调用 grepawk 等外部命令速度快得多。当逻辑更复杂或数据量很大时,再结合 awksed 等工具共同使用。掌握这些基础,你的 Shell 脚本就已经能够覆盖大部分日常运维和自动化需求了。