1、程序构成:

    主要由指令和数据构成,数据可以是变量、文件、数组


2、数组介绍:

变量:存储单个元素的内存空间

数组:存储多个元素的连续的内存空间


3、数组的特点:

    数组名:整个数组只有一个名字

    数组索引:元素编号从“0”开始,数组名[索引]


注意:对于bash-4及之后的版本,支持自定义的索引格式,而不仅仅是0,1,2....等等数字格式。同时数组可以不事先声明,可以直接使用,但是如果不声明,它会把多个字符串的变量当做一个变量,因此使用数组前,应先声明数组。


4、声明数组:(有两种方式)

    方式一:declare -a NAME  //声明索引数组,用0,1,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、数组练习示例:

①、生成10个随机数,并找出其中的最大值和最小值。

[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]# 


②、生成10个随机数字,而后进行由小到大进程排序。


③、写一个脚本实现如下功能

定义一个数组,数组中的元素是/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是指定的分隔符,功能是:自右向左,查找var变量所存储的字符串中,最后一次出现的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退出脚本。