linux_shellLinux其他开发工具

Linux Shell:Shell数组操作

2021-09-04  本文已影响0人  xiaogp

摘要:LinuxShell

Shell数组类型

Shell数组分为普通数组关联数组,普通数组就是相同类型的元素组成的以下标区分的集合,关联数组以key-value作为区分,类似于其他编程语言的Map结构


数组定义

(1)普通数组

普通数组以整数索引,可以直接定义也可以使用下标定义填充定义,直接定义使用圆括号(),元素之间用空格隔开

a=(python java scala)
echo ${a[0]}  # python

如果元素自带空格,需要用引号括起来

a=(a 'b c' a e)
echo ${a[1]}  # b c

填充定义直接起一个变量使用中括号[]定义下标和值

b[0]=python
b[1]=java
b[2]=scala
echo ${b[@]}  # python java scala
(2)关联数组

关联数组也可以直接定义key-value,也可以用空数组填充key-value定义,直接定义之前需要显式声明是关联数组,使用declare -A,普通数组不需要显式声明,默认创建的就是普通数组,如果要强行显式声明就是declare -a

declare -A c
c=([name]=xiaogp [height]=175 [weight]=70)
echo ${c[height]}  # 175

填充定义直接起一个变量使用中括号[]定义下标key值,在申明和调用key值时可以不使用双引号括起来

declare -A d
d[name]=xiaogp
d[height]=172
d[weight]=70
echo ${d[height]}  # 172

也可以写成一行

declare -A e
e[name]=xiaogp;e[height]=175;e[weight]=70
echo ${e[@]}  # 175 70 xiaogp

如果一个key被重复指定,则新值会覆盖旧值

map[a]=1
map[a]=2
echo ${map[a]}  # 2
(3)从文件中读取定义数组

可以通过catawk等命令将文件每一行的内容作为一个元素填充到数组,比如

a=(`cat test.txt`)

再看一个文件,使用逗号分隔符记录了一些数据

root@ubuntu:~# head -3 peTTM_rank.txt 
2021-07-02,sh.600695,*ST绿庭,2352.677378
2021-07-02,sz.300023,*ST宝德,1803.766121
2021-07-02,sh.600696,ST岩石,904.12449

使用awk选取第二列组成一个数组,将执行结果用圆括号包起来

a=(`awk -F "," '{print $2}' peTTM_rank.txt`)
# 或者a=($(awk -F "," '{print $2}' peTTM_rank.txt))

打印结果如下所有第二列被加入素组中

echo ${a[@]}
sh.600695 sz.300023 sh.600696 sz.000712 sh.600053 sh.600906 sh.603093 sh.601162 sh.600095 sz.300176 sh.601375 sz.000416 sh.601456 sh.601696 sz.300059 sz.000567
echo ${a[0]}  # sh.600695

如果要从文件中读取数据组成关联数组需要遍历

#/bin/bash
declare -A map
while read line
do
    key=`echo $line |awk  -F "," '{print $2}'`
        value=`echo $line |awk -F "," '{print $3}'`
        map[$key]=$value    
done < peTTM_rank.txt
echo ${map[sh.600696]}  # ST岩石
(4)数组元素删除

使用unset删除数组元素或者整个数组

a=('a' 'b' 'z' 'q')
unset a[2]
echo ${a[@]}  # a b q
unset a
echo ${a[@]}  # 输出空

数组表达式

常见的数组表达式如下

语法 描述
${!array[*]} 访问数组所有索引(key)
${!array[@]} 访问数组所有索引(key)
${array[*]} 访问数组所有的值(value)
$array{@} 访问数组所有的值(value)
${#array[@]} 获得数组元素个数
${array[0]} 获得数组第一个元素
${array[@]:1} 访问数据从下标1开始往后
${array[@]:1:2} 访问数据从下标1开始往后一共2个元素

下面做以下简单测试,array[@]和array[*]的区别是当有双引号在外面括起来时,前者是一个一个元素分隔的,后者是一个整体

a=(a b c d e a)
for i in "${a[*]}"; do echo $i; done
a b c d e a
for i in "${a[@]}"; do echo $i; done
a
b
c
d
e
a

测试获取数组长度

echo ${#a[@]}  # 6

元素截取,从下标1的元素开始

echo ${a[@]}
a b c d e a
echo ${a[@]:1}
b c d e a

获得数组的key值

declare -A a
a=([name]=xiaogp [age]=13)
echo ${!a[@]}  # name age

数据截取和元素替换

数组截取使用数组表达式,格式如下

${array[@]:start:length}

如果第二个冒号后的数字省略则代表取到最后,如果第一个冒号后面的数字省略则代表从第一个元素开始

a=('a' 'b' 'z' 'q' 'z' 'l')
echo ${a[@]:1:3}  # 从第二个元素到最后
b z q
echo ${a[@]:1}  # 从第二个元素往最后
b z q z l
echo ${a[@]::3}  # 第一个元素开始往后3个
a b z

数组元素的修改的格式如下

${array[@]/old/new}

类似于变量替换,但是貌似只支持所有元素替换,不能第一个找到的元素替换,如果要把替换完的数组赋值给一个新数组,必须要加圆括号阔起来

a=('a' 'b' 'a' 'z' 'd')
echo ${a[@]/a/b}  # b b b z d
b=(${a[@]/a/b})
echo ${b[@]}  # b b b z d

数组遍历

数组遍历采用while循环for循环皆可,while循环用于从文件读取数组

root@ubuntu:~/Shell# cat test.txt
asdsd
wewrer
dcef
while read line
 do 
    array[++i]=$line
done < test.txt
root@ubuntu:~/Shell# echo ${array[@]}
asdsd wewrer dcef

这个效果个直接将cat的结果传给圆括号一致

root@ubuntu:~/Shell# array2=(`cat test.txt`)
root@ubuntu:~/Shell# echo ${array[@]}
asdsd wewrer dcef
(1)普通数组遍历

for循环,从第二个元素开始遍历,使用in进行遍历

for i in ${a[@]:1}
do
    echo $i
done  # bc cd de

也可以使用下标进行遍历,先遍历下标,再通过下标获取值

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

也可以类似C语法的循环方法

for ((i=0;i<${#a[@]};i++))
do
    echo ${a[i]}
done

也可以复杂一点使用while循环,通过长度判断停止

i=0
while [ $i -lt ${#a[@]} ]
do 
    echo ${a[i]}
    let i++
done
(2)关联数组遍历

关联数组遍历先获得下标再获得值

declare -A a
a=([name]=xiaogp [age]=12 [height]=170)
for i in ${!a[@]}
do  
    echo ${a[$i]}  # 此处要加$引用
done

Shell数组实战

(1)读取文件进行数字统计

文件如下,需要统计第二列的出现次数

root@ubuntu:~/Shell# cat test.txt 
xiaogp A
xiaomf C
xiaomk D
xiaosa A
xiaonb C
xiaohy A
xiaone A
xiaopp D
xiaomm A
xiaojh B

统计代码如下

#!/bin/bash
declare -A map
while read line
do
    value=`echo $line |awk -F ' ' '{print $2}'`
    map[$value]=$[${map[$value]}+1]
done < test.txt
for i in A B C D
do
    echo ${i}的出现次数=${map[$i]}
done

运行脚本结果如下

root@ubuntu:~/Shell# bash test.sh
A的出现次数=5
B的出现次数=1
C的出现次数=2
D的出现次数=2
上一篇下一篇

猜你喜欢

热点阅读