Shell教程—Shell数组

数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。Shell中的数组有两类:普通数组和关联数组。普通数组就是我们熟悉的一维数组,它的索引只能为整数;关联数组实质是一种key-value的集合,key和value既可以是整数也可以是字符串。

一、Shell数组的基本语法

1、普通数组
(1)定义数组

Shell中没有多维数组的概念,只有一维数组,它的语法格式如下:

#一次赋一个值
array1[index1]=value1
array1[index2]=value2

#一次赋多个值,多个值之间用空格隔开
array2=(value1 value2 value3.....)

#可以使用declare -a arrayName定义(不常用,并且系统默认创建的就是普通数组)
declare -a arrayName
arrayName=(v1 v2 v3....)
(2)查看数组
#使用declare -a可以查看系统定义使用普通数组
declare -a
(3)访问数组中的元素

读取数组元素值的一般格式是:

#访问数组中的某一个元素(echo可有可无,只是为了将数组的值打印出来)
echo ${array[index]}

#访问数组中的全部元素
echo ${array[@]}
或
echo ${array[*]}

#获取数组的长度
echo ${#array[@]}

#获取数组的索引
echo ${!array[@]}

#从数组索引为2的位置开始截取数组
echo ${array[@]:2}
#从数组索引为2的位置开始截取数组3个元素
echo ${array[@]:2:3}
2、关联数组
(1)定义数组

关联数组可以理解为一种key-value集合,它的语法格式如下:

#先使用declare -A定义一个关联数组,关联数组必须先使用declare -A定义
declare  -A arrayName

#接着给关联数组赋值,同样可以单个单个赋值也可以多个赋值
arrayName[key1]=value1
arrayName[key2]=value2
arrayName[key3]=value3
或
arrayName=([key1](value1) [key2](value2) [key3](value)....)
(2)查看数组
#查看所有关联数组
declare -A
(3)访问数组元素

读取关联不能用整型下标值,而应该使用在定义时给定的key,一般格式是:

declare -A map

map=([zhanshan](29) (lisi)(45) (wangwu)(34))
#直接使用给定的key来访问元素
echo ${map[zhangshan]}

#访问数组中的全部元素
echo ${array[@]}
或
echo ${array[*]}

#获取数组的长度
echo ${#array[@]}

#获取数组的索引
echo ${!array[@]}

#从数组索引为2的位置开始截取数组
echo ${array[@]:2}
#从数组索引为2的位置开始截取数组3个元素
echo ${array[@]:2:3}

二、案例

1、将/etc/hosts每行host读取存入hosts数组(简单)
#!/bin/bash
i=0
while read line; do
   hosts[i++]=$line 
done </etc/hosts

#遍历数组
for i in ${!hosts[@]}; do
   echo "$i:${hosts[i]}"
done

执行结果:

2、编写一个脚本对给定文件中的数字进行排序,并输出

在numbers.txt文本中有大量(大约10w个)随机生成的数字,现在要求对这些数字进行排序

实现排序:

#!/bin/bash
read -p "Please input number text path: " path
if [ -n "$path" -a ! -f "$path" ]; then
  echo "$path: can not find"
  exit 1
fi

#重新定义分隔符,以“,”分隔数字
IFS=$","
#获取文件中的中数据
for number in `cat $psth`; do
    numbers[i++]=$number
done


#排序:使用冒泡排序
for((i=0;i<${#numbers[@]}-1;i++)); do
    for((j=0;j<${#numbers[@]}-i-1;j++)); do
        moved=0
        if [ ${numbers[j]} -gt ${numbers[j+1]} ]; then
            tmp=${numbers[j]}
            numbers[j]=${numbers[j+1]}
            numbers[j+1]=$tmp
            moved=1
        fi
    done
    #moved 为0 说明此趟没有发生元素的移动,即元素已经拍好序了,那就直接跳出循环
    if [ $moved -eq 0 ]; then
       break
    fi
done

#先把原来的文件备份一下,然后用排序好的内容覆盖原文件
cp $path $path.bak
echo  ${numbers[@]}>$path 

echo -e "\nComplete!"

执行结果:

3、统计/etc/passwd文件中不同Shell的个数

/etc/passwd文件中定义了许多Shell,现在需要统计不同Shell的个数

#!/bin/bash

declare -A counter

while read line; do
    key=`echo $line | awk -F":" '{print $NF}'`
    let counter[$key]++
done <"/etc/passwd"

printf "统计结果:\n"
for key in ${!counter[@]}; do
    printf "%-12s %-12d\n" $key ${counter[$key]}
done

echo -e "\nCompleted!"

执行结果:

留言区

还能输入500个字符