1、程序构成:
主要由指令和数据构成,数据可以是变量、文件、数组
2、数组介绍:
变量:存储单个元素的内存空间
数组:存储多个元素的连续的内存空间
3、数组的特点:
数组名:整个数组只有一个名字
数组索引:元素编号从“0”开始,数组名[索引]
注意:对于bash-4及之后的版本,支持自定义的索引格式,而不仅仅是0,1,2....等等数字格式。同时数组可以不事先声明,可以直接使用,但是如果不声明,它会把多个字符串的变量当做一个变量,因此使用数组前,应先声明数组。
4、声明数组:(有两种方式)
方式一:declare -a NAME //声明索引数组,用0,2,3....表示各元素
方式二:declare -A NAME //声明关联数组,自定义索引格式
5、给数组中元素赋值:
赋值方式 | 备注 |
①、一次只赋值一个元素: 格式:ARRAY_NAME[INDEX]=value 示例: [root@localhost ~]# declare -a animal [root@localhost ~]# animal[0]=pig [root@localhost ~]# animal[1]=sheep [root@localhost ~]# echo $animal //引用第“0”个元素 pig [root@localhost ~]# echo ${animal[1]} pig[1] [root@localhost ~]# |
|
②、一次赋值全部元素: 格式:ARRAY_NAME=("VALUE1" "VALUE2" "VALUE3" ...) //必须以空格键隔开各元素值 示例: [root@localhost ~]# weekdays=("monday" "tuesday" "wedsday") [root@localhost ~]# echo ${weekdays[2]} wedsday [root@localhost ~]# |
|
③、只赋值特定元素: 格式:ARRAY_NAME=([0]="VAL0" [1]="VAL1" [3]="VAL3") //可以不连续赋值,此种被称为稀疏数组。 示例: [root@localhost ~]# cigrate=([0]="najing" [1]="xiaosu" [4]="yuxi") [root@localhost ~]# echo ${cigrate[0]} najing [root@localhost ~]# echo ${cigrate[1]} xiaosu [root@localhost ~]# echo ${cigrate[2]} [root@localhost ~]# echo ${cigrate[3]} [root@localhost ~]# echo ${cigrate[4]} yuxi [root@localhost ~]# 注意:bash支持稀疏格式的数组。 |
|
④、read -a ARRAY_NAME //回车后输入输入元素 示例: [root@localhost ~]# read -a ARR_name jiangsu anhui hubei [root@localhost ~]# echo $ARR_name jiangsu [root@localhost ~]# |
|
⑤、关联数组: ARRAY_NAME[INDEX]=var //必须declare -A后才能使用关联数组 示例: [root@localhost ~]# declare -A world [root@localhost ~]# world[zh]=china [root@localhost ~]# world[en]=english [root@localhost ~]# echo $world [root@localhost ~]# echo $world[zh] [zh] [root@localhost ~]# echo $world[en] [en] [root@localhost ~]# |
6、数组元素引用:
格式: ${ARRAY_NAME[INDEX]} //必须加{ },因为不加,则只会引用ARRAY_NAME,而不是整个数组元素。
数组元素其他使用技巧:
①、数组元素的长度:(数组元素的个数) 格式一:${#ARRAY_NAME[*]} //如果不加*或@表示引用数组中的第一个元素的个数 格式二:${#ARRAY_NAME[@]} //如果不加*或@表示引用数组中的第一个元素的个数 示例: [root@localhost ~]# declare -a china//声明一个数组名为china [root@localhost ~]# china=("bejing" "hanghai" "guanzhou" "jiangsu") //给数组赋值 [root@localhost ~]# echo $china //此种将会输出数组中的第一个元素值 bejing [root@localhost ~]# echo ${#china[*]} //输出数组中元素的个数,即数组长度 4 [root@localhost ~]# echo ${#china[@]} //输出数组中元素的个数,即数组长度 4 [root@localhost ~]# echo ${#china} //若不加“*”或“@”,则表示输出数组中第一个元素字符的个数 6 [root@localhost ~]# |
|
②、数组中第一个元素的字符个数: 格式:${#ARRAY_NAME} 示例: [root@localhost ~]# declare -a china [root@localhost ~]# china=("bejing" "hanghai" "guanzhou" "jiangsu") [root@localhost ~]# echo ${#china} 6 |
|
③、引用或查看数组中的全部元素值 格式一:${ARRAY_NAME[*]} 格式二:${ARRAY_NAME[@]} [root@localhost ~]# declare -a china [root@localhost ~]# china=("bejing" "hanghai" "guanzhou" "jiangsu") [root@localhost ~]# echo ${chian[*]} bejing hanghai guanzhou jiangsu [root@localhost ~]# echo ${chian[@]} bejing hanghai guanzhou jiangsu [root@localhost ~]# |
|
④、数组元素切片 格式一:${ARRAY_NAME[@]:offset:number} 格式二:${ARRAY_NAME[*]:offset:number} offset:要略过的元素的个数,即偏移量,注意此处不是步长的概念。 number:要取出元素的个数,省略number时表示取偏移量之后的所有元素 示例: [root@localhost sh]# declare -a files [root@localhost sh]# files=(/etc/[Pp]*) [root@localhost sh]# echo ${files[@]} /etc/PackageKit /etc/pam.d /etc/pam_pkcs11 /etc/passwd /etc/passwd- /etc/pbm2ppa.conf /etc/pcp /etc/pcp.conf /etc/pcp.env /etc/Pegasus /etc/pinforc /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/pnm2ppa.conf /etc/polkit-1 /etc/popt.d /etc/portreserve /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/pulse /etc/purple /etc/python [root@localhost sh]# echo ${files[@]:2:2} /etc/pam_pkcs11 /etc/passwd [root@localhost sh]# echo ${files[*]:2:2} /etc/pam_pkcs11 /etc/passwd [root@localhost sh]# [root@localhost sh]# echo ${files[*]:10} /etc/pinforc /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/pnm2ppa.conf /etc/polkit-1 /etc/popt.d /etc/portreserve /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/pulse /etc/purple /etc/python [root@localhost sh]# |
|
⑤、向数组中追加元素(非稀疏格式) 格式一:ARRAY_NAME[{#ARRAY_NAME[@]}]=value //标红部分表示数组长度,即要追加元素的下标 格式二:ARRAY_NAME[{#ARRAY_NAME[*]}]=value //标红部分表示数组长度,即要追加元素的下标 |
|
⑥、删除数组中的某元素 撤销变量:#unset VAR //VAR是变量名 撤销数组中的某元素:#unset ARRAY[INDEX] //注意:不要加“$”因为撤销的是元素 |
7、数组练习示例:
[root@localhost sh]# cat array_max_min.sh
#!/bin/bash
declare -i max=0
declare -i min=0
declare -a array_int
for i in `seq 1 10` ;do
array_int[$i]=$RANDOM
echo ${array_int[$i]}
if [ $i -eq 1 ]; then
max=${array_int[$i]}
min=${array_int[$i]}
elif [ ${array_int[$i]} -gt $max ];then
max=${array_int[$i]}
elif [ ${array_int[$i]} -lt $min ];then
min=${array_int[$i]}
fi
done
echo "max=$max ; min=$min"
[root@localhost sh]#
③、写一个脚本实现如下功能
定义一个数组,数组中的元素是/var/log目录下所有以".log"结尾的文件,统计其下标为偶数的文件的行数之和。
[root@localhost sh]# cat array_pattern.sh
#!/bin/bash
declare -a files
files=(/var/log/*.log)
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"
[root@localhost sh]#
8、bash内置字符串处理:
8.1字符串切片: 格式:${var:offset:number}//var是变量名,offset是偏移量,number是取出的个数,整个意思是:取字符串的子串, 示例: [root@localhost ~]# name=changcheng [root@localhost ~]# echo ${name} changcheng [root@localhost ~]# echo ${name:2}//取偏移量之后所有字符 angcheng [root@localhost ~]# echo ${name:2:3} //取偏移量之后的3个字符 ang [root@localhost ~]# |
8.2、基于模式取子串: 格式一:${var#*word} //其中word是指定的分隔符,整个表达式的功能是:自左向右查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符。 示例: [root@localhost ~]# echo ${name} changcheng [root@localhost ~]# echo ${name#*ang} cheng [root@localhost ~]# 格式二:${var##*word} //其中word是指定的分隔符,整个表达式的功能是:自左向右,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符。 示例: [root@localhost ~]# mypath="/etc/init.d/functions" [root@localhost ~]# echo ${mypath} /etc/init.d/functions [root@localhost ~]# echo ${mypath#*/} etc/init.d/functions [root@localhost ~]# echo ${mypath##*/} //取路径基名 functions [root@localhost ~]# 格式三:${var%word*} //其中word是指定的分隔符,功能是:自右向左,查找var变量所存储的字符串中,第一次出现的word分隔符,删除此分隔符至字符串结尾部分之间的所有字符。 示例: [root@localhost ~]# mypath="/etc/init.d/functions" [root@localhost ~]# echo ${mypath} /etc/init.d/functions [root@localhost ~]# echo ${mypath%/*} //取路径名 /etc/init.d [root@localhost ~]# 格式四:${var%%word*} //其中word是指定的分隔符,功能是:最后一次出现的word分隔符,删除此分隔符至字符串结尾部分之间的所有字符。 示例: [root@localhost ~]# mypath="/etc/init.d/functions" [root@localhost ~]# echo ${mypath} /etc/init.d/functions [root@localhost ~]# echo ${mypath%%/*} [root@localhost ~]# [root@localhost ~]# myurl=http://www.magedu.com:80 [root@localhost ~]# echo ${myurl##*:}//取端口号 80 [root@localhost ~]# echo ${myurl%%:*} //取协议号 http [root@localhost ~]# |
8.3:、字符串查找和替换: 格式一:${var/PATTERN/SUBSTI}//查找var表示的字符串中,第一次被PATTERN所匹配的字符串,将其替换为SUBSTI所表示的字符串。 格式二:${var//PARTTERN/SUBSTI}//查找var表示的字符串中,所有被PATTERN所匹配的字符串,全部将其替换为SUBSTI所表示的字符串。 格式三:${var/#PATTERN/SUBSTI}//查找var表示的字符串中,行首被PATTERN所匹配的字符串,将其替换为SUBSTI所表示的字符串;注意:仅行首被匹配时才做替换。 格式四:${var/%PATTERN/SUBSTI}//查找var表示的字符串中,行尾被PATTERN所匹配的字符串,将其替换为SUBSTI所表示的字符串;注意:仅行尾被匹配时才做替换。 注意:此处的PATTERN仅适用glob风格的通配模式。 示例: [root@localhost ~]# userinfo=`head -1 /etc/passwd` [root@localhost ~]# echo ${userinfo} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/root/user} user:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo//root/user} user:x:0:0:user:/user:/bin/bash [root@localhost ~]# echo ${userinfo/#oot/mage} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/#roo/mage} maget:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/%roo/mage} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/%bas/mage} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/%bash/mage} root:x:0:0:root:/root:/bin/mage [root@localhost ~]# |
8.4、字符串的查找删除: 格式一:${var/PATTERN} //以PATTERN为模式,查找var字符串中第一次的匹配,并删除。 格式二:${var//PATTERN} //以PATTERN为模式,查找var字符串中所有匹配的字符串,并删除。 格式三:${var/#PATTERN} //以PATTERN为模式,查找var字符串中仅行首匹配到的字符串,并删除。 格式四:${var/%PATTERN} //以PATTERN为模式,查找var字符串中仅行尾匹配的字符串,并删除。 示例: [root@localhost ~]# userinfo=$(head -1 /etc/passwd) [root@localhost ~]# echo ${userinfo} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/root} :x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo//root} :x:0:0::/:/bin/bash [root@localhost ~]# echo ${userinfo/#root} :x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/%root} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo/%bash} root:x:0:0:root:/root:/bin/ [root@localhost ~]# |
8.5、字符串大小写转换: 格式一:${var^^} //把var中所有小写字符转成大写字符 格式二:${var,} //把var中所有大写字符转成小写字符 示例: [root@localhost ~]# userinfo=$(head -1 /etc/passwd) [root@localhost ~]# echo ${userinfo} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${userinfo^^} ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH [root@localhost ~]# [root@localhost ~]# say="ILoveU" [root@localhost ~]# echo ${say} ILoveU [root@localhost ~]# echo ${say,} iloveu [root@localhost ~]# |
8.6、变量赋值: 格式一:${var:-VALUE} //var是变量;表示如果var变量为空,或者未设置,那么返回VALUE,否则返回var变量的值。 格式二:${var:=VALUE} //var是变量;表示如果var变量为空,或者未设置,那么返回VALUE,并将VALUE赋值给var变量,否则返回var变量的值。 格式三:${var:+VALUE} //如果var变量不为空,则返回VALUE值。 格式四:${var:?ERROR_INFO} //如果var为空,或者未设置,那么返回ERROR_INFO为错误提示,否则,返回var值。 示例: [root@localhost ~]# echo ${xuexiao} [root@localhost ~]# echo ${xuexiao:-nanda} nanda [root@localhost ~]# echo ${xuexiao:=nanda} nanda [root@localhost ~]# echo ${xuexiao} nanda [root@localhost ~]# echo ${xuexiao:+beida} beida [root@localhost ~]# echo ${xuexiao:?buzhidao} nanda [root@localhost ~]# echo ${xuexiao1:?buzhidao} bash: xuexiao1: buzhidao [root@localhost ~]# |
9、练习:写一个脚本,实现如下功能:
②、获取此命令所依赖的所有的库文件列表(ldd),把此目录当根
③、复制命令至某目标文件(例如:/mnt/sysroot)下的对应路径中,
例如:bash,/bin/bash ==>/mnt/sysroot/bin/bash
④、复制此命令依赖到的所有库文件至目标目录下的对应路径下:
例如:/lib64/ld-linux-x86_64.so.2 ==>/mnt/sysroot//lib64/ld-linux-x86_64.so.2
⑤、每次复制完成一个命令后,不要退出,而是提示用户继续输入要复制的其他命令,并重复完成如上述所描述的功能,直到用户输入quit退出脚本。