目录

6.4 数组与算数运算

数组与算数运算

/images/linux_mt/linux_mt.jpg

本节我们来学习 bash shell 编程的第四部分内容数组与算数运算。

1. 数组

数组和字典是编程中非常常用的数据结构,但是 bash 对它们支持都比较有限。原因我们在本章第一节就说过,bash 本质上并不能算一种语言,因此也很少被拿来做复杂的编程。它更适合利用 Linux 中已有的命令完成特定功能。所以 bash 对复杂数据结构的支持很有限。bash 4.0 之后才开始支持字典,默认也只支持一维数组。下面我们将通过数组的声明,赋值和引用来讲解数组的使用。

bash 中字典又称为关联数组,使用方式与数组基本一致,只是将数字索引改为,字符串索引即可

1.1 数组声明

数组和字典的声明:

  1. 数组声明: declare -a
  2. 字典声明: declare -A, bash 4.0及以上才支持,必需显示声明

1.2 数组的赋值

bash 中的数组有多种赋值方式,常用的如下所示

赋值方式 语法
一次只赋值一个元素 a[0]=$RANDOM
一次赋值全部元素 a=(red blue yellow green)
只赋值特定元素 a=([0]=green [3]=red [2]=blue [6]=yellow)
用户输入 read -a ARRAY
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 数组赋值支持通配符
logs=(/var/log/*.log)

# 字典赋值
declare  -A  world
world[us]="america"
echo  "${world['us']}"

# 向非稀疏数组追加元素
ARRAY[${#ARRAY[*]}]=value

1.3 数组的访问

变量引用可以使用 ${VARIABLE},而数组的访问就是在此基础上添加上要访问的索引。需要特别注意的是数组引用 {}不可省略,否则[index] 会被当作普通字符对待

  1. 用索引访问:
    • ${ARRAY[index]}
  • ${ARRAY}: 没有下标时,默认引用索引为 0 的元素
  1. 访问整个数组:
    • ${ARRAY[@]}: 每个参数是一个独立的串
    • ${ARRAY[*]}: 所有参数是一个串
  2. 数组切片:
    • ${ARRAY[@]:offset:number}: 取出偏移两之后特定数量的元素
    • ${ARRAY[@]:offset}:取出偏移量后的所有元素
    • ${ARRAY[@]}: 取出所有元素
  • 说明: offset是偏移的元素个数,number 是取出的元素的个数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 获取数组的长度:  
echo ${#ARRAY[*]}`
echo ${#ARRAY[@]}`
# 获取数组第 0 个元素的字符串长度
echo ${#ARRAY}

tao@hp$ world[0]=us
tao@hp$ echo ${#world[*]}  # 数组长度
1
tao@hp$ echo ${#world}     # 数组 0 元素的字符长度
2

1.4 从数组中删除元素:

unset ARRAY[index]

2. 数组使用示例

示例 1

定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;统计其下标为偶数的文件中的行数之和;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/bin/bash
#
declare -a files
files=(/var/log/*.log)

declare -i lines=0

for i in $(seq 0 $[${#files[*]}-1]); do
  if [ $[$i%2] -eq 0 ]; then
    let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
  fi
done

echo "Lines: $lines."

示例 2

生成10个随机数,升序排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
#
for((i=0;i<10;i++))
do
  rnd[$i]=$RANDOM
done

echo -e "total=${#rnd[@]}\n${rnd[@]}\nBegin to sort"

for((i=9;i>=1;i--))
do
  for((j=0;j<i;j++))
  do
    if [ ${rnd[$j]} -gt ${rnd[$[$j+1]]} ] ;then
      swapValue=${rnd[$j]}
      rnd[$j]=${rnd[$[$j+1]]}
      rnd[$[$j+1]]=$swapValue		
    fi
  done
done

echo ${rnd[@]}

2. 算术运算

bash 是弱类型编程语言,所有变量的默认类型是字符串。因此算术运算必需借助特定的命令来实现。同时 bash 中默认也不支持浮点数,当然也几乎用不到

常见的算术运算符包括 +,-,*,/, **, %,bash中实现算术运算有如下几种方式:

  1. let var=3+4: let 不会打印输出,只能使用变量进行保存
  2. let count+=2: let 支持增量赋值 +=,-=,*=, /=, %=
  3. let count++: let 支持自增运算
  4. var=$[$var+1]
  5. var=$(($var+1))
  6. var=$(expr 3 \* 4): 运算符和操作数之间必须使用空格分割,* 需要转义
  7. $RANDOM: bash 内置的随机数生成器,表示 1-32767 的随机数
    • echo $[$RANDOM%60]
  8. 注意:乘法符号在有些场景中需要使用转义符;
1
2
3
4
5
6
7
脚本练习:
# 计算/etc/passwd文件中的第10个用户和第20个用户的id号之和;
id1=$(head -10  /etc/passwd | tail -1  | cut  -d:  -f3)
id2=$(head -20   /etc/passwd | tail -1  | cut  -d:  -f3)

# 计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和;
grep "^[[:space:]]*$"   /etc/rc.d/init.d/functions | wc -l