第166集:数组操作

教学目标

  • 掌握Shell脚本中数组的定义和初始化方法
  • 学习数组元素的访问和修改
  • 理解数组的长度计算和遍历方法
  • 掌握数组元素的添加和删除
  • 学习数组的排序和反转操作
  • 理解多维数组的使用
  • 能够在脚本中灵活使用数组处理数据

主要知识点

  1. 数组的定义和初始化
  2. 数组元素的访问和修改
  3. 数组长度的计算
  4. 数组的遍历
  5. 数组元素的添加和删除
  6. 数组的排序和反转
  7. 多维数组
  8. 数组的切片和拼接

实用案例分析

案例1:基本数组操作

目标:学习在Shell脚本中定义和使用基本数组。

操作步骤

  1. 创建基本数组操作演示脚本
# 创建脚本文件
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[@]}"
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x basic-arrays.sh

# 运行脚本
./basic-arrays.sh

案例2:数组遍历

目标:学习在Shell脚本中遍历数组元素。

操作步骤

  1. 创建数组遍历演示脚本
# 创建脚本文件
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
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x array-iteration.sh

# 运行脚本
./array-iteration.sh

案例3:数组元素的添加和删除

目标:学习在Shell脚本中添加和删除数组元素。

操作步骤

  1. 创建数组元素添加和删除演示脚本
# 创建脚本文件
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[@]}"
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x array-modification.sh

# 运行脚本
./array-modification.sh

案例4:数组排序和反转

目标:学习在Shell脚本中对数组进行排序和反转操作。

操作步骤

  1. 创建数组排序和反转演示脚本
# 创建脚本文件
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[@]}"
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x array-sort-reverse.sh

# 运行脚本
./array-sort-reverse.sh

案例5:多维数组

目标:学习在Shell脚本中使用多维数组。

操作步骤

  1. 创建多维数组演示脚本
# 创建脚本文件
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
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x multi-dimensional-arrays.sh

# 运行脚本
./multi-dimensional-arrays.sh

案例6:数组的高级操作

目标:学习数组的切片、拼接等高级操作。

操作步骤

  1. 创建数组高级操作演示脚本
# 创建脚本文件
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[@]}"
  1. 运行脚本并查看结果
# 设置执行权限
chmod +x array-advanced.sh

# 运行脚本
./array-advanced.sh

课后练习

  1. 基础练习

    • 创建一个脚本,定义一个数组并计算所有元素的和
    • 编写一个脚本,使用数组存储用户输入并显示
    • 设计一个脚本,对数组元素进行排序并显示
  2. 进阶练习

    • 创建一个脚本,使用数组实现简单的栈数据结构
    • 编写一个脚本,使用数组存储系统进程信息并进行分析
    • 设计一个脚本,使用数组实现简单的学生成绩管理系统
  3. 挑战练习

    • 编写一个脚本,使用数组实现冒泡排序算法
    • 创建一个脚本,使用多维数组存储和处理复杂数据
    • 设计一个脚本,使用数组实现简单的文本搜索引擎

总结

本集详细介绍了Linux Shell脚本中的数组操作,包括数组的定义、初始化、访问、修改、遍历、排序、反转等内容。通过学习这些知识,读者可以在Shell脚本中灵活使用数组来处理和管理数据。

数组是Shell脚本编程中的重要数据结构,它允许将多个相关的值存储在一个变量中,便于统一管理和操作。掌握数组操作是编写复杂Shell脚本的基础。

通过本集的学习,读者应该能够理解和使用基本的数组操作,掌握数组元素的访问和修改,理解数组的长度计算和遍历方法,掌握数组元素的添加和删除,学习数组的排序和反转操作,以及理解多维数组的使用。这些知识将为后续学习字符串处理和文件操作打下基础。

« 上一篇 函数定义 下一篇 » 字符串处理