bash-基础--数组和字符切片
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bash-基础--数组和字符切片相关的知识,希望对你有一定的参考价值。
数组
什么是数组?
变量:存储单个元素的内存空间;
数组:存储多个元素的连续的内存空间;
数组名:整个数组只有一个名字;
数组索引:编号从0开始;
数组名[索引], ${ARRAY_NAME[INDEX]}
注意:bash-4及之后的版本,支持自定义索引格式,而不仅仅是0,1,2,...数字格式;
此类数组称之为“关联数组”
声明数组:
declare -a NAME:声明索引数组;
declare -A NAME:声明关联数组;
数组中元素的赋值方式:
(1) 一次只赋值一个元素; ARRAY_NAME[INDEX]=value
(2) 一次赋值全部元素;ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只赋值特定元素;ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...)
注意:bash支持稀疏格式的数组;
(4) read -a ARRAY_NAME 引用数组中的元素:${ARRAY_NAME[INDEX]}
注意:引用时,只给数组名,表示引用下标为0的元素;
数组的长度(数组中元素的个数):
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
示例:生成10个随机数,并找出其中的最大值和最小值;
#!/bin/bash # declare -a rand declare -i max=0 for i in {0..9}; do rand[$i]=$RANDOM echo ${rand[$i]} [ ${rand[$i]} -gt $max ] && max=${rand[$i]} done
echo "MAX: $max"
练习:定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;统计其下标为偶数的文件中的行数之和;
#!/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."
引用数组中的所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
数组元素切片: ${ARRAY_NAME[@]:offset:number}
offset:要路过的元素个数;
number:要取出的元素个数;省略number时,表示取偏移量之后的所有元素;
向非稀疏格式数组中追加元素:ARRAY_NAME[${#ARRAY_NAME[*]}]=
删除数组中的某元素:unset ARRAY[INDEX]
关联数组:
declare -A ARRAY_NAME 注:声明一个数组变量
ARRAY_NAME=([index_name1]="value1" [index_name2]="value2" ...)
字串切片
bash的内置字符串处理工具:
字符串切片:${var:offset:number}
取字符串的子串;取字符趾的最右侧的几个字符:${var: -length}
注意:冒号后必须有一个空白字符;
基于模式取子串:
1、${var#*word}:其中word是指定的分隔符;功能:自左而右,查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符;
2、${var##*word}:其中word是指定的分隔符;功能:自左而右,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符;
举例:mypath="/etc/init.d/functions"
3、${mypath##*/}: functions
4、${mypath#*/}: etc/init.d/functions
5、${var%word*}:其中word是指定的分隔符;功能:自右而左,查找var变量所存储的字符串中,第一次出现的word分隔符,删除此分隔符至字符串尾部之间的所有字符;
6、${var%%word*}:其中word是指定的分隔符;功能:自右而左,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除此分隔符至字符串尾部之间的所有字符;
举例:mypath="/etc/init.d/functions"
7、${mypath%/*}: /etc/init.d
举例:url=http://www.magedu.com:80
8、${url##*:}
9、${url%%:*}
查找替换:
1、${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;
2、${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并将其全部替换为SUBSTI所表示的字符串;
4、${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;
5、${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;
注意:PATTERN中使用glob风格和通配符;
查找删除:
1、${var/PATTERN}:以PATTERN为模式查找var字符串中第一次的匹配,并删除之;
2、${var//PATERN}
3、${var/#PATTERN}
4、${var/%PATTERN}
字符大小写转换:
1、${var^^}:把var中的所有小写字符转换为大写;
2、${var,,}:把var中的所有大写字符转换为小写;
3、变量赋值:
4、${var:-VALUE}:如果var变量为空,或未设置,那么返回VALUE;否则,则返回var变量的值;
5、${var:=VALUE}:如果var变量为空,或未设置,那么返回VALUE,并将VALUE赋值给var变量;否则, 则返回var变量的值;
6、${var:+VALUE}:如果var变量不空,则返回VALUE;
7、${var:?ERROR_INFO}:如果var为空,或未设置,那么返回ERROR_INFO为错误提示;否则,返回var值;
写一个脚本:
ping命令去查看172.16.1.1-172.16.67.1范围内的所有主机是否在线;在线的显示为up, 不在线的显示down,分别统计在线主机,及不在线主机数;
分别使用for, while和until循环实现。
for循环实现方式
#!/bin/bash # declare -i uphosts=0 declare -i downhosts=0 for i in {1..17}; do if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then echo "172.16.$i.1 is up." let uphosts+=1 else echo "172.16.$i.1 is down." let downhosts+=1 fi done echo "Up hosts: $uphosts, Down hosts: $downhosts."
while循环实现方式:
#!/bin/bash # declare -i uphosts=0 declare -i downhosts=0 declare -i i=1 hostping() { if ping -W 1 -c 1 $1 &> /dev/null; then echo "$1 is up." return 0 else echo "$1 is down." return 1 fi } while [ $i -le 67 ]; do hostping 172.16.$i.1 [ $? -eq 0 ] && let uphosts++ || let downhosts++ let i++ done echo "Up hosts: $uphosts, Down hosts: $downhosts."
写一个脚本,实现:
能探测C类、B类或A类网络中的所有主机是否在线;
#!/bin/bash # cping() { local i=1 while [ $i -le 5 ]; do if ping -W 1 -c 1 $1.$i &> /dev/null; then echo "$1.$i is up" else echo "$1.$i is down." fi let i++ done } bping() { local j=0 while [ $j -le 5 ]; do cping $1.$j let j++ done } aping() { local x=0 while [ $x -le 255 ]; do bping $1.$x let x++ done }
信号捕捉trap
trap ‘COMMAND‘ SIGNALS 注:捕捉到 SIGNALS ,就执行‘COMMAND‘
常可以进行捕捉的信号:HUP, INT(ctrl +c )
提示用户输入一个IP地址或网络地址;获取其网络,并扫描其网段;
信号捕捉示例: #!/bin/bash # declare -a hosttmpfiles trap ‘mytrap‘ INT mytrap() { echo "Quit" rm -f ${hosttmpfiles[@]} exit 1 } for i in {1..50}; do tmpfile=$(mktemp /tmp/ping.XXXXXX) if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then echo "172.16.$i.1 is up" | tee $tmpfile else echo "172.16.$i.1 is down" | tee $tmpfile fi hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfile done rm -f ${hosttmpfiles[@]}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
编外补充:
练习:写一个脚本,完成如下功能
(1) 提示用户输入一个可执行命令的名称;
(2) 获取此命令所依赖到的所有库文件列表;
(3) 复制命令至某目标目录(例如/mnt/sysroot,即把此目录当作根)下的对应的路径中
bash, /bin/bash ==> /mnt/sysroot/bin/bash
useradd, /usr/sbin/useradd ==> /mnt/sysroot/usr/sbin/useradd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下;
/lib64/ld-linux-x8664.so.2 ==> /mnt/sysroot/lib64/ld-linux-x8664.so.2
进一步:
每次复制完成一个命令后,不要退出,而是提示用户继续输入要复制的其它命令,并重复完成如上所描述的功能;直到用户输入“quit”退出脚本;
在bash中使用ACSII颜色
\033[31m hello \033[0m
##m:
左侧#:
3:前景色
4:背景色
右侧#:颜色种类
1, 2, 3, 4, 5, 6, 7
#m:
加粗、闪烁等功能;
多种控制符,可组合使用,彼此间用分号隔开;
dialog命令可实现窗口化编程;
各窗体控件使用方式;
如何获取用户选择或键入的内容?
默认,其输出信息被定向到了错误输出流;
《高级bash编程指南》,《Linux命令行和shell脚本编程宝典》
本文出自 “学而思” 博客,请务必保留此出处http://7136230.blog.51cto.com/7126230/1758599
以上是关于bash-基础--数组和字符切片的主要内容,如果未能解决你的问题,请参考以下文章