第166集:数组操作
教学目标
- 掌握Shell脚本中数组的定义和初始化方法
- 学习数组元素的访问和修改
- 理解数组的长度计算和遍历方法
- 掌握数组元素的添加和删除
- 学习数组的排序和反转操作
- 理解多维数组的使用
- 能够在脚本中灵活使用数组处理数据
主要知识点
- 数组的定义和初始化
- 数组元素的访问和修改
- 数组长度的计算
- 数组的遍历
- 数组元素的添加和删除
- 数组的排序和反转
- 多维数组
- 数组的切片和拼接
实用案例分析
案例1:基本数组操作
目标:学习在Shell脚本中定义和使用基本数组。
操作步骤:
- 创建基本数组操作演示脚本
# 创建脚本文件
touch basic-arrays.sh
# 编辑脚本文件
vim basic-arrays.sh
# 添加以下内容
#!/bin/bash
# 演示基本数组操作
# 1. 定义数组
fruits=(apple banana cherry date)
# 2. 访问数组元素
echo "=== Accessing array elements ==="
echo "First element: ${fruits[0]}"
echo "Second element: ${fruits[1]}"
echo "Third element: ${fruits[2]}"
echo "Fourth element: ${fruits[3]}"
# 3. 修改数组元素
echo "\n=== Modifying array elements ==="
echo "Before modification: ${fruits[1]}"
fruits[1]="blueberry"
echo "After modification: ${fruits[1]}"
# 4. 访问所有数组元素
echo "\n=== Accessing all array elements ==="
echo "All elements: ${fruits[@]}"
echo "All elements (alternative): ${fruits[*]}"
# 5. 计算数组长度
echo "\n=== Calculating array length ==="
echo "Array length: ${#fruits[@]}"
echo "Array length (alternative): ${#fruits[*]}"
# 6. 定义空数组
empty_array=()
echo "\n=== Empty array ==="
echo "Empty array length: ${#empty_array[@]}"
# 7. 定义索引数组
indexed_array=([0]="first" [2]="third" [5]="fifth")
echo "\n=== Indexed array ==="
echo "Element at index 0: ${indexed_array[0]}"
echo "Element at index 2: ${indexed_array[2]}"
echo "Element at index 5: ${indexed_array[5]}"
echo "All elements: ${indexed_array[@]}"
echo "Array length: ${#indexed_array[@]}"- 运行脚本并查看结果
# 设置执行权限
chmod +x basic-arrays.sh
# 运行脚本
./basic-arrays.sh案例2:数组遍历
目标:学习在Shell脚本中遍历数组元素。
操作步骤:
- 创建数组遍历演示脚本
# 创建脚本文件
touch array-iteration.sh
# 编辑脚本文件
vim array-iteration.sh
# 添加以下内容
#!/bin/bash
# 演示数组遍历
# 定义数组
fruits=(apple banana cherry date blueberry)
# 1. 使用for循环遍历
echo "=== Using for loop to iterate ==="
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
# 2. 使用索引遍历
echo "\n=== Using index to iterate ==="
for ((i=0; i<${#fruits[@]}; i++)); do
echo "Index $i: ${fruits[$i]}"
done
# 3. 使用while循环遍历
echo "\n=== Using while loop to iterate ==="
i=0
while [ $i -lt ${#fruits[@]} ]; do
echo "Index $i: ${fruits[$i]}"
i=$((i + 1))
done
# 4. 遍历并处理数组元素
echo "\n=== Processing array elements ==="
for fruit in "${fruits[@]}"; do
echo "Processing: $fruit"
# 转换为大写
upper_fruit=$(echo "$fruit" | tr '[:lower:]' '[:upper:]')
echo "Uppercase: $upper_fruit"
done
# 5. 遍历命令输出到数组
echo "\n=== Iterating over command output ==="
files=($(ls -la | grep "^-" | awk '{print $9}'))
echo "Found ${#files[@]} files:"
for file in "${files[@]}"; do
echo "- $file"
done- 运行脚本并查看结果
# 设置执行权限
chmod +x array-iteration.sh
# 运行脚本
./array-iteration.sh案例3:数组元素的添加和删除
目标:学习在Shell脚本中添加和删除数组元素。
操作步骤:
- 创建数组元素添加和删除演示脚本
# 创建脚本文件
touch array-modification.sh
# 编辑脚本文件
vim array-modification.sh
# 添加以下内容
#!/bin/bash
# 演示数组元素的添加和删除
# 初始数组
fruits=(apple banana cherry)
echo "=== Initial array ==="
echo "Fruits: ${fruits[@]}"
echo "Length: ${#fruits[@]}"
# 1. 在数组末尾添加元素
echo "\n=== Adding elements to end ==="
fruits+="date"
echo "After adding 'date': ${fruits[@]}"
# 添加多个元素
fruits+=("blueberry" "elderberry")
echo "After adding multiple elements: ${fruits[@]}"
echo "Length: ${#fruits[@]}"
# 2. 在指定位置添加元素
echo "\n=== Adding element at specific position ==="
# 在索引1处添加元素
fruits=(${fruits[@]:0:1} "kiwi" ${fruits[@]:1})
echo "After adding 'kiwi' at index 1: ${fruits[@]}"
echo "Length: ${#fruits[@]}"
# 3. 删除数组元素
echo "\n=== Removing array elements ==="
# 删除索引2处的元素
unset fruits[2]
echo "After removing element at index 2: ${fruits[@]}"
echo "Length: ${#fruits[@]}"
# 注意:删除元素后,数组索引不会重新排序
# 遍历所有索引(包括空索引)
echo "\n=== Iterating with indexes ==="
for i in "${!fruits[@]}"; do
echo "Index $i: ${fruits[$i]}"
done
# 4. 重建数组(去除空元素)
echo "\n=== Rebuilding array ==="
fruits=(${fruits[@]})
echo "After rebuilding: ${fruits[@]}"
echo "Length: ${#fruits[@]}"
# 遍历重建后的数组索引
for i in "${!fruits[@]}"; do
echo "Index $i: ${fruits[$i]}"
done
# 5. 清空数组
echo "\n=== Clearing array ==="
unset fruits
echo "After clearing: ${fruits[@]}"
echo "Length: ${#fruits[@]}"- 运行脚本并查看结果
# 设置执行权限
chmod +x array-modification.sh
# 运行脚本
./array-modification.sh案例4:数组排序和反转
目标:学习在Shell脚本中对数组进行排序和反转操作。
操作步骤:
- 创建数组排序和反转演示脚本
# 创建脚本文件
touch array-sort-reverse.sh
# 编辑脚本文件
vim array-sort-reverse.sh
# 添加以下内容
#!/bin/bash
# 演示数组排序和反转
# 1. 数值数组排序
numbers=(5 2 8 1 9 3 7 4 6)
echo "=== Numeric array sorting ==="
echo "Original: ${numbers[@]}"
# 排序(升序)
sorted_numbers=($(echo "${numbers[@]}" | tr ' ' '\n' | sort -n))
echo "Sorted (ascending): ${sorted_numbers[@]}"
# 排序(降序)
reverse_sorted=($(echo "${numbers[@]}" | tr ' ' '\n' | sort -nr))
echo "Sorted (descending): ${reverse_sorted[@]}"
# 2. 字符串数组排序
fruits=(cherry apple banana date blueberry)
echo "\n=== String array sorting ==="
echo "Original: ${fruits[@]}"
# 排序(按字母顺序)
sorted_fruits=($(echo "${fruits[@]}" | tr ' ' '\n' | sort))
echo "Sorted (alphabetical): ${sorted_fruits[@]}"
# 排序(反向字母顺序)
reverse_sorted_fruits=($(echo "${fruits[@]}" | tr ' ' '\n' | sort -r))
echo "Sorted (reverse alphabetical): ${reverse_sorted_fruits[@]}"
# 3. 数组反转
echo "\n=== Array reversal ==="
original=(1 2 3 4 5)
echo "Original: ${original[@]}"
# 使用tac命令反转
reversed=($(echo "${original[@]}" | tr ' ' '\n' | tac))
echo "Reversed: ${reversed[@]}"
# 4. 自定义排序(例如按字符串长度)
echo "\n=== Custom sorting (by string length) ==="
words=(apple banana cherry date blueberry)
echo "Original: ${words[@]}"
# 按字符串长度排序
sorted_by_length=($(for word in "${words[@]}"; do echo "$word"; done | awk '{print length, $0}' | sort -n | cut -d' ' -f2-))
echo "Sorted by length: ${sorted_by_length[@]}"
# 5. 排序并去除重复元素
echo "\n=== Sorting and removing duplicates ==="
duplicates=(apple banana apple cherry banana date apple)
echo "Original (with duplicates): ${duplicates[@]}"
# 排序并去重
sorted_unique=($(echo "${duplicates[@]}" | tr ' ' '\n' | sort | uniq))
echo "Sorted and unique: ${sorted_unique[@]}"- 运行脚本并查看结果
# 设置执行权限
chmod +x array-sort-reverse.sh
# 运行脚本
./array-sort-reverse.sh案例5:多维数组
目标:学习在Shell脚本中使用多维数组。
操作步骤:
- 创建多维数组演示脚本
# 创建脚本文件
touch multi-dimensional-arrays.sh
# 编辑脚本文件
vim multi-dimensional-arrays.sh
# 添加以下内容
#!/bin/bash
# 演示多维数组
# 1. 模拟二维数组(使用一维数组)
echo "=== Simulating 2D array ==="
# 定义3x3的二维数组
array=(1 2 3 4 5 6 7 8 9)
# 访问元素(行=2, 列=1,索引从0开始)
rows=3
cols=3
row=2
col=1
index=$((row * cols + col))
echo "Element at ($row, $col): ${array[$index]}"
# 遍历二维数组
echo "\n=== Iterating 2D array ==="
for ((i=0; i<rows; i++)); do
for ((j=0; j<cols; j++)); do
index=$((i * cols + j))
echo -n "${array[$index]} "
done
echo
done
# 2. 使用关联数组模拟二维数组
echo "\n=== Using associative array for 2D ==="
declare -A matrix
matrix[0,0]=1
matrix[0,1]=2
matrix[0,2]=3
matrix[1,0]=4
matrix[1,1]=5
matrix[1,2]=6
matrix[2,0]=7
matrix[2,1]=8
matrix[2,2]=9
# 访问元素
echo "Element at (1, 1): ${matrix[1,1]}"
# 遍历关联数组
echo "\n=== Iterating associative 2D array ==="
for key in "${!matrix[@]}"; do
echo "$key: ${matrix[$key]}"
done
# 3. 数组的数组(嵌套数组)
echo "\n=== Array of arrays ==="
# 定义嵌套数组
array1=(1 2 3)
array2=(4 5 6)
array3=(7 8 9)
# 将数组存储在另一个数组中
nested=('${array1[@]}' '${array2[@]}' '${array3[@]}')
# 注意:这种方法需要特殊处理才能正确访问
# 4. 实际应用:存储表格数据
echo "\n=== Storing tabular data ==="
# 学生成绩表
students=(
"Alice Math 95"
"Alice English 88"
"Bob Math 92"
"Bob English 90"
"Charlie Math 85"
"Charlie English 95"
)
# 遍历并显示学生成绩
echo "Student Grade Table:"
echo "---------------------"
for student in "${students[@]}"; do
read name subject score <<< "$student"
echo "$name: $subject = $score"
done
# 计算平均成绩
echo "\n=== Calculating average scores ==="
declare -A total_scores
declare -A subject_count
for student in "${students[@]}"; do
read name subject score <<< "$student"
total_scores[$subject]=$((total_scores[$subject] + score))
subject_count[$subject]=$((subject_count[$subject] + 1))
done
for subject in "${!total_scores[@]}"; do
average=$((total_scores[$subject] / subject_count[$subject]))
echo "Average $subject score: $average"
done- 运行脚本并查看结果
# 设置执行权限
chmod +x multi-dimensional-arrays.sh
# 运行脚本
./multi-dimensional-arrays.sh案例6:数组的高级操作
目标:学习数组的切片、拼接等高级操作。
操作步骤:
- 创建数组高级操作演示脚本
# 创建脚本文件
touch array-advanced.sh
# 编辑脚本文件
vim array-advanced.sh
# 添加以下内容
#!/bin/bash
# 演示数组的高级操作
# 定义数组
numbers=(0 1 2 3 4 5 6 7 8 9)
echo "=== Original array ==="
echo "Numbers: ${numbers[@]}"
# 1. 数组切片
echo "\n=== Array slicing ==="
# 从索引2开始,取3个元素
slice1=${numbers[@]:2:3}
echo "Slice from index 2, 3 elements: ${slice1[@]}"
# 从索引5开始,取所有剩余元素
slice2=${numbers[@]:5}
echo "Slice from index 5 to end: ${slice2[@]}"
# 从索引0开始,取5个元素
slice3=${numbers[@]:0:5}
echo "First 5 elements: ${slice3[@]}"
# 2. 数组拼接
echo "\n=== Array concatenation ==="
array1=(1 2 3)
array2=(4 5 6)
array3=(7 8 9)
# 拼接数组
combined=(${array1[@]} ${array2[@]} ${array3[@]})
echo "Combined array: ${combined[@]}"
# 3. 数组交集
echo "\n=== Array intersection ==="
arrayA=(apple banana cherry date)
arrayB=(banana date elderberry fig)
# 计算交集
intersection=()
for item in "${arrayA[@]}"; do
for compare in "${arrayB[@]}"; do
if [ "$item" = "$compare" ]; then
intersection+="$item"
break
fi
done
done
echo "Array A: ${arrayA[@]}"
echo "Array B: ${arrayB[@]}"
echo "Intersection: ${intersection[@]}"
# 4. 数组差集
echo "\n=== Array difference ==="
# A - B
difference=()
for item in "${arrayA[@]}"; do
found=false
for compare in "${arrayB[@]}"; do
if [ "$item" = "$compare" ]; then
found=true
break
fi
done
if [ "$found" = false ]; then
difference+="$item"
fi
done
echo "A - B: ${difference[@]}"
# 5. 数组元素查找
echo "\n=== Array element search ==="
search_array=(apple banana cherry date blueberry)
search_term="cherry"
found=false
index=-1
for i in "${!search_array[@]}"; do
if [ "${search_array[$i]}" = "$search_term" ]; then
found=true
index=$i
break
fi
done
if [ "$found" = true ]; then
echo "Found '$search_term' at index $index"
else
echo "'$search_term' not found in array"
fi
# 6. 数组元素替换
echo "\n=== Array element replacement ==="
original=(apple banana cherry date)
echo "Original: ${original[@]}"
# 替换所有匹配的元素
replaced=()
for item in "${original[@]}"; do
if [ "$item" = "cherry" ]; then
replaced+="strawberry"
else
replaced+="$item"
fi
done
echo "After replacement: ${replaced[@]}"- 运行脚本并查看结果
# 设置执行权限
chmod +x array-advanced.sh
# 运行脚本
./array-advanced.sh课后练习
基础练习
- 创建一个脚本,定义一个数组并计算所有元素的和
- 编写一个脚本,使用数组存储用户输入并显示
- 设计一个脚本,对数组元素进行排序并显示
进阶练习
- 创建一个脚本,使用数组实现简单的栈数据结构
- 编写一个脚本,使用数组存储系统进程信息并进行分析
- 设计一个脚本,使用数组实现简单的学生成绩管理系统
挑战练习
- 编写一个脚本,使用数组实现冒泡排序算法
- 创建一个脚本,使用多维数组存储和处理复杂数据
- 设计一个脚本,使用数组实现简单的文本搜索引擎
总结
本集详细介绍了Linux Shell脚本中的数组操作,包括数组的定义、初始化、访问、修改、遍历、排序、反转等内容。通过学习这些知识,读者可以在Shell脚本中灵活使用数组来处理和管理数据。
数组是Shell脚本编程中的重要数据结构,它允许将多个相关的值存储在一个变量中,便于统一管理和操作。掌握数组操作是编写复杂Shell脚本的基础。
通过本集的学习,读者应该能够理解和使用基本的数组操作,掌握数组元素的访问和修改,理解数组的长度计算和遍历方法,掌握数组元素的添加和删除,学习数组的排序和反转操作,以及理解多维数组的使用。这些知识将为后续学习字符串处理和文件操作打下基础。