Shell 数组

Shell 数组是处理多个数据的集合,支持一维数组(普通数组)和关联数组(键值对)。以下是 Shell 数组的详细讲解:


一、数组的定义

1. 普通数组

普通数组的索引从 0 开始,支持整数作为下标。

  • 直接定义

    array=(value0 value1 value2)
    

    示例:

    fruits=("apple" "banana" "orange")
    
  • 指定下标定义

    array=([0]="a" [2]="b" [5]="c")
    

    输出:a(下标0)、空(下标1未定义)、b(下标2)、空(下标3-4未定义)、c(下标5)。

  • 间接定义

    list="value1 value2 value3"
    array=($list)
    
2. 关联数组

关联数组支持字符串或整数作为键(下标),需先声明再使用。

  • 声明与定义

    关联数组使用 declare 命令来声明

    declare -A info
    info=([name]="Alice" [age]=25 [city]="Shanghai")
    

二、数组的访问

1. 访问单个元素
  • 普通数组:

    echo ${array[0]}  # 访问第一个元素
    
  • 关联数组:

    echo ${info[name]}  # 访问键为"name"的值
    
2. 访问所有元素
  • 使用 @*

    echo ${array[@]}  # 所有元素,用空格分隔
    echo ${array[*]}  # 效果同上
    

    注意:后面会讲解一下区别

3. 获取数组长度
  • 元素个数

    length=${#array[@]}  # 或 ${#array[*]}
    
  • 单个元素长度

    length_of_element=${#array[0]}  # 获取第一个元素的字符数
    
4. 获取所有下标

在数组前加一个感叹号 ! 可以获取数组的所有键

echo ${!array[@]}  # 输出所有下标(如:0 1 2)
echo ${!array[*]}  # 输出所有下标(如:0 1 2)

三、数组的操作

1. 添加元素
  • 追加到末尾

    array+=("new_element")
    
  • 指定下标添加

    array[3]="d"
    
2. 修改元素
array[1]="updated_value"
3. 删除元素
  • 删除单个元素

    unset array[1]  # 删除下标为1的元素,数组下标不会重新排序
    
  • 删除整个数组

    unset array
    
4. 数组切片
  • 语法:${array[@]:起始位置:长度}

    echo ${array[@]:1:2}  # 从下标1开始,取2个元素
    
5. 数组拼接
array1=(1 2 3)
array2=(4 5 6)
combined=("${array1[@]}" "${array2[@]}")
6. 数组替换
array=(${array[@]/old_value/new_value})  # 替换所有匹配项

四、数组的遍历

1. 普通遍历
for item in "${array[@]}"; do
  echo "$item"
done

注意:使用双引号包裹 ${array[@]},避免元素中包含空格时被错误分割。

2. 带索引的遍历
for i in "${!array[@]}"; do
  echo "Index $i: ${array[$i]}"
done

五、关联数组的特殊操作

  1. 声明关联数组

    declare -A map
    
  2. 赋值

    map[key1]="value1"
    
  3. 遍历键和值

    for key in "${!map[@]}"; do
        echo "Key: $key, Value: ${map[$key]}"
    done
    

六、常见注意事项

  1. 下标从0开始:普通数组的下标必须为非负整数。

  2. 空格分隔元素:数组元素之间用空格分隔,逗号会被当作一个整体。

    array=(1,2,3)  # 错误:会被当作一个元素(值为"1,2,3")
    array=(1 2 3)   # 正确
    
  3. 元素可为空:未定义的下标访问时会返回空。

  4. unset后索引不重排:删除元素后,其他元素的下标不会改变。

    array=(a b c)
    unset array[1]
    echo ${array[@]}  # 输出 a c
    echo ${!array[@]} # 输出 0 2
    

七、@*区别💥

在 Shell 数组中,@* 都可以用来获取数组的所有元素,但它们的行为在是否被双引号包裹的情况下有显著区别。以下是详细对比:

1. 未被双引号包裹时(无引号)

  • @* 的行为相同
    两者都会将数组的每个元素视为独立的字符串,彼此之间用空格分隔。

  • 示例

    arr=(a b c)
    echo ${arr[@]}  # 输出: a b c
    echo ${arr[*]}  # 输出: a b c
    

2. 被双引号包裹时(有引号)

  • @* 的行为不同
    • ${array[@]}
      将数组的每个元素视为独立的字符串,并保留每个元素的原始内容(包括空格)。
      在循环中,每个元素会被单独处理。
    • ${array[*]}
      将数组的所有元素合并为一个字符串(默认用空格分隔),并作为一个整体处理。
      在循环中,整个字符串会被视为单个元素。

示例 1:普通元素

arr=(a b c)

# 使用 ${array[@]}
for i in "${arr[@]}"; do
  echo "$i"
done
# 输出:
# a
# b
# c

# 使用 ${array[*]}
for i in "${arr[*]}"; do
  echo "$i"
done
# 输出:
# a b c

示例 2:元素包含空格

arr=("hello world" "good morning")

# 使用 ${array[@]}
for i in "${arr[@]}"; do
  echo "$i"
done
# 输出:
# hello world
# good morning

# 使用 ${array[*]}
for i in "${arr[*]}"; do
  echo "$i"
done
# 输出:
# hello world good morning

3. 关键区别总结

场景${array[@]}${array[*]}
未被双引号包裹每个元素独立,用空格分隔每个元素独立,用空格分隔
被双引号包裹每个元素独立,保留空格等原始内容所有元素合并为一个字符串(默认空格分隔)
适用场景遍历数组、处理带空格的元素合并所有元素为一个整体

4. 推荐用法

  • 遍历数组时
    始终使用 ${array[@]},因为它能正确处理带空格的元素。

    for item in "${arr[@]}"; do
      echo "$item"
    done
    
  • 合并所有元素为一个字符串时
    使用 ${array[*]},但需注意默认分隔符是空格(可通过 IFS 修改)。

    IFS=','  # 修改分隔符为逗号
    joined="${arr[*]}"	
    echo "$joined"  # 输出: a,b,c
    

5. 特殊变量的类比

@* 的区别也适用于 Shell 的特殊变量(如 $@$*):

  • $@:表示所有脚本参数(或函数参数),每个参数独立。
  • $*:表示所有参数合并为一个字符串(默认空格分隔)。

例如:

# 脚本 test.sh
for arg in "$*"; do
  echo "arg: $arg"
done

# 执行脚本
./test.sh a b c
# 输出:
# arg: a b c

总结

  • @:始终将数组(或参数)的每个元素视为独立个体。
  • *:将数组(或参数)合并为一个整体(默认空格分隔)。
    在需要保留元素独立性(尤其是处理带空格的字符串)时,优先使用 ${array[@]}

八、示例代码

#!/bin/bash

# 定义普通数组
fruits=("apple" "banana" "orange")

# 添加元素
fruits+=("grape")

# 修改元素
fruits[1]="blueberry"

# 获取长度
echo "Length: ${#fruits[@]}"

# 访问所有元素
echo "All elements: ${fruits[@]}"

# 访问单个元素
echo "Third element: ${fruits[2]}"

# 数组切片
echo "Slice: ${fruits[@]:1:2}"

# 删除元素
unset fruits[1]

# 遍历数组
for fruit in "${fruits[@]}"; do
    echo "Fruit: $fruit"
done

# 定义关联数组
declare -A person
person[name]="Alice"
person[age]=30

# 遍历关联数组
for key in "${!person[@]}"; do
    echo "$key: ${person[$key]}"
done

九、总结

  • Shell 数组支持普通数组和关联数组,适用于存储和操作一组数据。
  • 掌握数组的定义、访问、修改、遍历和高级操作(如切片、拼接)是编写高效 Shell 脚本的关键。
  • 注意空格分隔、下标索引和 unset 操作的影响,避免常见错误。

👍 自由不是随心所欲,而是自我掌控的能力

😊 **希望对你有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡续命又一天

一杯续命美式,续写下一篇干货

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值