Shell 脚本中的数组操作包括数组的定义、访问、遍历和常用操作。
数组定义
普通数组
bash# 定义空数组 arr=() # 定义数组(空格分隔) arr=(apple banana cherry) # 逐个定义 arr[0]="apple" arr[1]="banana" arr[2]="cherry" # 使用命令输出定义数组 arr=($(ls *.txt))
关联数组(Bash 4.0+)
bash# 声明关联数组 declare -A arr # 定义关联数组 arr[name]="John" arr[age]=25 arr[city]="Beijing" # 一次性定义 declare -A arr=([name]="John" [age]=25 [city]="Beijing")
数组访问
访问单个元素
basharr=(apple banana cherry) # 访问特定索引的元素 echo ${arr[0]} # 输出: apple echo ${arr[1]} # 输出: banana echo ${arr[2]} # 输出: cherry # 访问最后一个元素 echo ${arr[-1]} # 输出: cherry # 访问不存在的索引 echo ${arr[10]} # 输出: (空)
访问所有元素
bash# 访问所有元素 echo ${arr[@]} # 输出: apple banana cherry echo ${arr[*]} # 输出: apple banana cherry # 访问所有元素的索引 echo ${!arr[@]} # 输出: 0 1 2 # 访问数组长度 echo ${#arr[@]} # 输出: 3 echo ${#arr[*]} # 输出: 3
访问部分元素
bash# 访问从索引 1 开始的所有元素 echo ${arr[@]:1} # 输出: banana cherry # 访问从索引 1 开始的 2 个元素 echo ${arr[@]:1:2} # 输出: banana cherry # 访问从倒数第 2 个元素开始 echo ${arr[@]: -2} # 输出: banana cherry
数组遍历
遍历所有元素
basharr=(apple banana cherry) # 方法 1: 使用 for 循环 for item in "${arr[@]}"; do echo "Item: $item" done # 方法 2: 使用索引遍历 for i in "${!arr[@]}"; do echo "Index $i: ${arr[$i]}" done # 方法 3: 使用 C 风格循环 for ((i=0; i<${#arr[@]}; i++)); do echo "Index $i: ${arr[$i]}" done
遍历关联数组
bashdeclare -A arr=([name]="John" [age]=25 [city]="Beijing") # 遍历键 for key in "${!arr[@]}"; do echo "Key: $key" done # 遍历键值对 for key in "${!arr[@]}"; do echo "$key: ${arr[$key]}" done
数组操作
添加元素
basharr=(apple banana) # 添加到末尾 arr+=(cherry) arr+=("date" "fig") # 添加到特定位置 arr[2]="cherry" # 替换或添加 # 使用索引添加 arr[${#arr[@]}]="grape" # 添加到末尾
删除元素
basharr=(apple banana cherry date fig) # 删除特定索引的元素 unset arr[2] # 删除索引 2 的元素 # 删除整个数组 unset arr # 删除关联数组的元素 declare -A arr=([name]="John" [age]=25) unset arr[name]
修改元素
basharr=(apple banana cherry) # 修改特定索引的元素 arr[0]="orange" arr[1]="pear" # 批量修改 for i in "${!arr[@]}"; do arr[$i]="${arr[$i]}_modified" done
数组切片
basharr=(one two three four five) # 切片操作 echo ${arr[@]:1:3} # 输出: two three four # 切片并赋值 new_arr=(${arr[@]:1:3})
数组排序
简单排序
basharr=(banana apple cherry date) # 字典序排序 sorted=($(echo "${arr[@]}" | tr ' ' '\n' | sort)) echo "${sorted[@]}" # 数字排序 nums=(5 2 8 1 9) sorted_nums=($(echo "${nums[@]}" | tr ' ' '\n' | sort -n)) echo "${sorted_nums[@]}" # 逆序排序 sorted_rev=($(echo "${arr[@]}" | tr ' ' '\n' | sort -r)) echo "${sorted_rev[@]}"
去重
basharr=(apple banana apple cherry banana) # 去重 unique=($(echo "${arr[@]}" | tr ' ' '\n' | sort -u)) echo "${unique[@]}"
数组查找
查找元素
basharr=(apple banana cherry) # 检查元素是否存在 if [[ " ${arr[@]} " =~ " banana " ]]; then echo "Found banana" fi # 使用函数查找 contains_element() { local e match="$1" shift for e; do [[ "$e" == "$match" ]] && return 0; done return 1 } if contains_element "banana" "${arr[@]}"; then echo "Found banana" fi
查找索引
basharr=(apple banana cherry) # 查找元素索引 get_index() { local element=$1 shift local arr=("$@") for i in "${!arr[@]}"; do if [[ "${arr[$i]}" == "$element" ]]; then echo $i return 0 fi done return 1 } index=$(get_index "banana" "${arr[@]}") echo "Index of banana: $index"
实际应用示例
文件处理
bash# 获取所有 .txt 文件 files=($(ls *.txt)) # 遍历并处理 for file in "${files[@]}"; do echo "Processing: $file" # 处理文件 done # 检查文件是否存在 if [ ${#files[@]} -eq 0 ]; then echo "No .txt files found" fi
参数处理
bash# 将参数存储到数组 args=("$@") # 遍历参数 for arg in "${args[@]}"; do echo "Argument: $arg" done # 检查特定参数 if [[ " ${args[@]} " =~ " --verbose " ]]; then verbose=true fi
数据统计
bash# 读取数据到数组 readarray -t lines < data.txt # 统计行数 echo "Total lines: ${#lines[@]}" # 统计包含特定内容的行 count=0 for line in "${lines[@]}"; do if [[ "$line" =~ "pattern" ]]; then ((count++)) fi done echo "Matching lines: $count"
配置管理
bash# 解析配置文件到关联数组 declare -A config while IFS='=' read -r key value; do config[$key]="$value" done < config.txt # 访问配置 echo "Database: ${config[db_host]}" echo "Port: ${config[db_port]}"
数组最佳实践
- 始终使用引号:
"${arr[@]}"防止空格和特殊字符问题 - 使用 ${#arr[@]} 获取长度: 而不是 ${#arr}
- 使用 ${!arr[@]} 获取索引: 遍历时更安全
- 关联数组需要声明:
declare -A声明关联数组 - 避免使用未初始化的索引: 检查索引是否存在
- 使用函数封装复杂操作: 提高代码可读性
- 注意数组索引从 0 开始: 与其他编程语言一致