本篇内容介绍了“shell脚本中数组的用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
问题描述:某个员工的linux系统有大量重复的软件(版本不同),导致使用yum安装软件时报错。现在需要将重复的软件找出来,将低版本的软件删掉。执行rpm -qa | sort 显示如下:
[root@cws85 ~]# rpm -qa | sort a52dec-0.7.4-27.el7.x86_64 aalib-libs-1.4.0-0.22.rc5.el7.x86_64 abattis-cantarell-fonts-0.0.25-1.el7.noarch abrt-2.1.11-52.el7.centos.x86_64 abrt-addon-ccpp-2.1.11-52.el7.centos.x86_64 abrt-addon-kerneloops-2.1.11-52.el7.centos.x86_64 abrt-addon-pstoreoops-2.1.11-52.el7.centos.x86_64 abrt-addon-python-2.1.11-52.el7.centos.x86_64 abrt-addon-vmcore-2.1.11-52.el7.centos.x86_64 abrt-addon-xorg-2.1.11-52.el7.centos.x86_64 abrt-cli-2.1.11-52.el7.centos.x86_64 abrt-console-notification-2.1.11-52.el7.centos.x86_64 abrt-dbus-2.1.11-52.el7.centos.x86_64 abrt-desktop-2.1.11-52.el7.centos.x86_64 abrt-gui-2.1.11-52.el7.centos.x86_64 abrt-gui-libs-2.1.11-52.el7.centos.x86_64 abrt-java-connector-1.0.6-12.el7.x86_64 abrt-libs-2.1.11-52.el7.centos.x86_64 abrt-python-2.1.11-52.el7.centos.x86_64 abrt-retrace-client-2.1.11-52.el7.centos.x86_64 abrt-tui-2.1.11-52.el7.centos.x86_64 accountsservice-0.6.50-4.el7.1.x86_64 accountsservice-libs-0.6.50-4.el7.1.x86_64 acl-2.2.51-14.el7.x86_64 adcli-0.8.1-6.el7_6.1.x86_64 adwaita-cursor-theme-3.28.0-1.el7.noarch adwaita-gtk2-theme-3.28-2.el7.x86_64 adwaita-icon-theme-3.28.0-1.el7.noarch adwaita-qt5-1.0-1.el7.x86_64 aic94xx-firmware-30-6.el7.noarch alsa-firmware-1.0.28-2.el7.noarch alsa-lib-1.1.6-2.el7.x86_64 alsa-plugins-pulseaudio-1.1.6-1.el7.x86_64 alsa-tools-firmware-1.1.0-1.el7.x86_64 alsa-utils-1.1.6-1.el7.x86_64 anaconda-core-21.48.22.121-1.el7.centos.x86_64 anaconda-core-21.48.22.147-1.el7.centos.0.1.x86_64 anaconda-gui-21.48.22.147-1.el7.centos.0.1.x86_64 anaconda-tui-21.48.22.121-1.el7.centos.x86_64 #这是重复软件的低版本 anaconda-tui-21.48.22.147-1.el7.centos.x86_64 #这是重复软件的高版本 anaconda-widgets-21.48.22.147-1.el7.centos.0.1.x86_64 ..........省略 总共2586个软件
要求:如上所示,需要将低版本的软件删除,如下是例外:
[root@cws85 ~]# rpm -qa | grep audit-libs-[0-9]
audit-libs-2.8.4-4.el7.i686
audit-libs-2.8.4-4.el7.x86_64
虽然是重复软件,但一个是x86_64,一个是i686,这样不能删除,只能删除重复的_x86_64结尾的软件
数组:脚本中用到了数组,下面是数组的部分内容概述:
1.数组定义:
declare -a 数组名 #定义索引数组,下标从0开始
declare -A 数组名 #定义关联数组,下标为任意字符
2.数组赋值与复制:
2.1.可以通过命令替换的方式给数组赋值: declare -a SOFT1=($(rpm -qa | sort)) #数组SOFT1保存着所有软件
2.2.数组复制操作:linux2=(${linux1[@]}) #数组linux2复制了数组linux1的内容
3.数组的字符串操作:
3.1.字符串的操作符可以用在数组上,如:${#string} 用于数组 ${#array[@]},等等等等。
3.2.数组遍历: for i in ${!SOFT[@]} #注意加上感叹号可以遍历数组中的值,假设SOFT的下标最大是2586,通过for循环可以遍历完数组,i的值从0依次到2586。
脚本内容:
#!/bin/bash declare -a SOFT1=($(rpm -qa | sort)) #数组SOFT1保存所有软件名称 for i in ${!SOFT1[*]} #遍历数组SOFT1 do declare -a SOFT2[$i]=${SOFT1[$i]%%-[0-9]*} #数组SOFT2复制数组SOFT1的部分内容,%%是字符串截取符号,相当于去掉软件的版本号,只保留软件名称 done for i in $(seq 0 $((${#SOFT2[@]}-1))) #遍历数组SOFT2 do let "j=$i+5" for (( ;i<j;j--)) #i小于j时跳出循环,循环执行5次 do if [ "${SOFT2[$i]}" == "${SOFT2[$j]}" ] #测试是否有重复软件 then declare -a SOFT3=($(rpm -qa | grep "^${SOFT2[$i]}-[0-9]" | sort)) #如果软件有重复,执行rpm -qa | grep 重复软件名,赋值给数组SOFT3 if (( "${#SOFT3[@]}" < 2 )) #检测数组SOFT3的下标个数是否小于2(多加一层保险) then echo "${SOFT2[$i]} no repeat version" >>/tmp/soft && continue #小于2输出该软件没有重复的版本 elif (( "${#SOFT3[@]}" > 2 )) #如果下标大于2,也就是(rpm -qa | grep 重复软件)有多于2个软件 then X86=0 I686=0 #初始化两个变量,用于后面比较 for i in ${!SOFT3[*]} #遍历数组SOFT3 do [[ "${SOFT3[$i]##*.}" == "i686" ]] && I686=$((I686+1)) || X86=$((X86+1)) #如果软件名结尾是i686,那么变量I686加1,否则X86加1 done (( "$X86" >= "$I686" )) && echo "${SOFT3[0]} can1 delete" >>/tmp/soft #如果X86值大于I686,输出软件能够删除 elif (( "${#SOFT3[@]}" == 2 )) #如果下标等于2,也就是(rpm -qa | grep 重复软件)有两个 then [[ "${SOFT3[0]##*.}" == "i686" || "${SOFT3[1]##*.}" == "i686" ]] && { echo "${SOFT3[0]} only two packages but has I686" >>/tmp/soft ; continue ; } #两个软件里只要有1个是i686结尾的,输出不能删除 echo "${SOFT3[0]} can2 delete" >>/tmp/soft fi fi done done
脚本说明:
1.数组SOFT1保存所有软件的完整名称,数组SOFT2是通过数组复制加上字符串的替换,截取出不带版本名称的软件名,比如 SOFT1[4]=abrt-addon-ccpp-2.1.11-52.el7.centos.x86_64, SOFT2[4]=abrt-addon-ccpp。
2.利用for循环遍历数组SOFT2来检测那些是重复软件,如下:
for i in $(seq 0 $((${#SOFT2[@]}-1))) #遍历数组SOFT2 do let "j=$i+5" #j比i大5,用于测试某个软件名与它后面的5个软件名是否相等,因为是通过rpm -qa | sort排序过,所以软件名都是按照字母顺序排的,比较5个就可以了。 for (( ;i<j;j--)) do if [ "${SOFT2[$i]}" == "${SOFT2[$j]}" ] #比较是否有重复软件名
3.如果有重复,需要处理软件后缀名的问题,只有重复的以X86结尾的软件名才输出该软件可以删除。利用数组SOFT3=($(rpm -qa | grep "^${SOFT2[$i]}-[0-9]" | sort)) 来保存搜索出的重复软件,然后在进行判断比较
脚本输出结果:输出被重定向到文件里,文件内容如下:
anaconda-core-21.48.22.121-1.el7.centos.x86_64 can2 delete anaconda-tui-21.48.22.121-1.el7.centos.x86_64 can2 delete audit-libs-2.8.4-4.el7.i686 only two packages but has I686 avahi-libs-0.6.31-17.el7.x86_64 can2 delete bzip2-libs-1.0.6-13.el7.i686 only two packages but has I686 copy-jdk-configs-2.2-5.el7_4.noarch can2 delete cracklib-2.9.0-11.el7.i686 only two packages but has I686 cryptsetup-libs-1.7.4-3.el7_4.1.x86_64 can2 delete dbus-1.10.24-13.el7_6.x86_64 can2 delete dbus-libs-1.10.24-13.el7_6.x86_64 can2 delete device-mapper-event-libs-1.02.149-10.el7_6.3.x86_64 can2 delete elfutils-libelf-0.172-2.el7.i686 only two packages but has I686 elfutils-libs-0.172-2.el7.i686 only two packages but has I686 fprintd-0.5.0-4.0.el7_0.x86_64 can2 delete freetype-2.8-12.el7_6.1.i686 only two packages but has I686 glib2-2.54.2-2.el7.x86_64 can2 delete glibc-2.17-260.el7_6.6.i686 only two packages but has I686 ........省略 总共81行,能删除的有52行(有少数错误,后面说明)
脚本调试信息:sh -x 脚本名显示的部分内容如下:
+ SOFT1=($(rpm -qa | sort)) #数组SOFT1保存完整软件名 ++ rpm -qa ++ sort + declare -a SOFT1 + for i in '${!SOFT1[*]}' #遍历数组SOFT1 + declare -a 'SOFT2[0]=a52dec' #给数组SOFT2赋值,只保留软件名 + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[1]=aalib-libs' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[2]=abattis-cantarell-fonts' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[3]=abrt' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[4]=abrt-addon-ccpp' + ..............省略,总共2586个 ++ seq 0 2585 + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' #遍历数组SOFT2,测试哪些是重复软件 + let j=0+5 #总共比较5次 + (( 1 )) + (( i<j )) + '[' a52dec == abrt-addon-kerneloops ']' + (( j-- )) + (( i<j )) + '[' a52dec == abrt-addon-ccpp ']' + (( j-- )) + (( i<j )) + '[' a52dec == abrt ']' + (( j-- )) + (( i<j )) + '[' a52dec == abattis-cantarell-fonts ']' + (( j-- )) + (( i<j )) + '[' a52dec == aalib-libs ']' #a53dec...不是一个重复软件 + (( j-- )) + (( i<j )) + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' #比较下一个,数组下标加1 + let j=1+5 ...........................................................................省略 + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' + let j=35+5 #数组下标到35 + (( 1 )) + (( i<j )) + '[' anaconda-core == anaconda-widgets ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-tui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-tui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-gui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-core ']' #这里找到重复软件 + SOFT3=($(rpm -qa | grep "^${SOFT2[$i]}-[0-9]" | sort)) #数组SOFT3赋值=(rpm -qa |grep ^anaconda-core-[0-9]|sort) ++ rpm -qa ++ sort ++ grep '^anaconda-core-[0-9]' + declare -a SOFT3 + (( 2 < 2 )) + (( 2 > 2 )) + (( 2 == 2 )) #刚好有两个包 + [[ x86_64 == i686 ]] #第一个包后缀是x86_64 + [[ x86_64 == i686 ]] #第二个包后缀是x86_64 + echo 'anaconda-core-21.48.22.121-1.el7.centos.x86_64 can2 delete' #输出能删除 + ..........................省略
脚本输出错误:脚本输出文件里总共有52行是能删除的软件,其中有几个是错误的,由于软件名称导致的错误,如下:
错误1: 软件名称: 字符-数字-字符-版本号 导致判断错误
java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64 can1 delete
java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64 can1 delete
SOFT2[$i]=${SOFT1[$i]%%-[0-9]*} #问题就在截取软件名称上,SOFT2=java, 正确的应该是SOFT2=java-1.8.0-openjdk。
错误2:错误的软件名称结尾,该软件没有以.X86或其他结尾
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
在给SOFT1赋值的时候需要过滤掉这种没有以.X86或其他后缀结尾的软件
总结:很少在脚本中用到数组,通过这个脚本加深了对数组的掌握与应用。不知道怎么解决脚本输出中的错误1这种问题,大部分的软件都能正确去掉版本号,个别的软件名就不行,感觉总会有漏洞。该脚本主要在于练习数组的应用,同时也能从二千多个软件里面找出重复软件,虽然有个别错误,但也会比用眼睛找重复软件好,对照着输出文件来删除软件会轻松很多。
“shell脚本中数组的用法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。