索引数组中说到数组中有元素删除时,使用for((expr1;expr2;expr3 ))访问,如何过滤掉unset状态的元素。

$ array_name=([0]="a" [1]="bb" [2]="ccc" [3]="dddd")


$ unset array_name[2]


$ for((i=0;i<=4-1;i++)); do echo ${array_name[i]}; done 

a

bb


dddd

$


给出2种方法:


第1种,若能获取到数组array_name的索引,那缺失索引代表的元素就是unset状态。在字符串处理中提到了变量扩展,其提供了获取数组索引列表的功能(不包含被删除元素的索引),基本形式是${!name[@]}或${!name[@*}。

$ echo ${!array_name[@]}

0 1 3


$ for i in $(echo ${!array_name[@]}); do echo ${array_name[$i]}; done

a

bb

dddd


该方法类似于索引数组中说到的第一种for循环,相比稍微有些啰嗦。

$ for i in "${array_name[@]}"; do echo $i; done

a

bb

dddd


第2种,第二种for循环for((i=0;i<=4-1;i++)),访问到了unset状态的元素,能否直接判断出其为unset状态呢?


字符串处理中提到的变量扩展中说到了变量赋值的4种形式,其会根据变量的unset或空值状态,进行下一步处理。与其对应的还有4种形式,其会根据变量的unset状态,进行下一步处理。对应关系,及其含义如下。

${parameter:-word} -> ${parameter-word}:若变量parameter未设置,就返回word(变量parameter状态不变);否则返回变量parameter的值(用于测试变量unset状态)。


${parameter:=word} -> ${parameter=word}:若变量parameter未设置,就将word赋值给变量parameter,然后返回变量parameter的值(变量parameter状态发生改变)。否则返回变量parameter的值。


${parameter:?word} -> ${parameter?word}:若变量parameter未设置,就输出word至STDERR(变量parameter状态不变);否则返回变量parameter的值。


${parameter:+word} -> ${parameter+word}:若变量parameter是非空值或空值,就返回word(变量parameter原值不变);否则返回变量parameter原状态值。


根据第一条规则可判断出unset状态的元素(不使用第二条,是其改变了数组状态)。

$ for((i=0;i<=4-1;i++)); do flag=${array_name[i]-word}; test "$flag" == "word" || echo ${array_name[i]}; done

a

bb

dddd


这里再想下如何判断变量是空值状态呢?对于unset,或空值状态的变量,长度都是0。

$ unset parameter

$ echo ${#parameter}

0


$ parameter=""

$ echo ${#parameter}

0


根据第四条规则,若变量parameter是非空值或空值,且长度为0,则其为空值状态。



说到Bash中数组这种数据类型,和Python中的list差不多,对于list常见操作有append,pop和insert,Bash数组也能模拟出这些动作(其中第二,三组,也是变量扩展提供的功能)。


In [26]: array_name=["a", "bb", "ccc", "dddd"]

In [27]: array_name.append("zz")

对应:

$ array_name=([0]="a" [1]="bb" [2]="ccc" [3]="dddd")

$ array_name=(${array_name[@]} "zz")


In [31]: array_name.pop()

Out[31]: 'zz'

对应:

$ array_name=(${array_name[@]:0:$((${#array_name[@]}-1))})


In [33]: array_name.pop(0)

Out[33]: 'a'

对应:

$ array_name=(${array_name[@]:1})


In [44]: array_name.insert(0,"yy")

对应:

$ array_name=("yy" ${array_name[@]})



另外在索引数组也提到了,Bash也支持关联数组(无顺序性),使用时需进行显式定义。


$ declare -A array

$ array=([width]=2 [height]=4 [depth]=6)


$ for i in ${!array[@]}; do echo ${array[$i]}; done 

6

4

2


若感兴趣可关注订阅号”数据库最佳实践”(DBBestPractice).

qrcode_for_gh_54ffa7e55478_258.jpg