Linux Shell:Shell数组操作

摘要: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)从文件中读取定义数组

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

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
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容