系统基础之shell脚本编程详解4(数组及字符串处理,变量赋值和配置文件)
今天来讲shell脚本编程的最后一些内容,数组及字符串处理,变量赋值和配置文件.这些内容也是我们经常在工作中使用到的知识点.下面让我们来详细了解下:
数组:
程序=指令+数据
指令:编程语法的关键字,调用系统命令,编写的函数
数据:变量,文件
变量:存储单个元素的内存空间;
数组:存储多个元素的连续的内存空间;(连续的内存空间存储连续的元素,元素有独立的空间,但只有一个统一的名字,索引表示各个元素)
数组名:整个数组只有一个名字;数组的标识,数组名指向的存储多个元素的内存空间起始地址的标识
数组索引:编号从0开始,1,2,3..N
使用方式:数组名[索引]
${ARRAY_NAME[INDEX]}
注意:bash-4及以后的版本,支持自定义索引格式,而不仅仅是0,1,2..数字格式;
此类数组称之为"关联数组"
声明数组:
declare -a name: 声明索引数组
declare -A name: 声明关联数组(自定义下标的数组,必须声明)
也可不声明,直接使用
animals[0]=pig
animals[1]=dog
引用数组:
1.直接引用数组名,显示第一个数组的元素. echo $animals
2.指定引用元素:
数组的赋值方式:
1.一次只复制一个元素
ARRAY_name[IDX]=value
2.一次复制全部元素
ARRAY_name=("mem" "TUS" "web")
3.只赋值特定元素:
ARRAY_name=([0]="mem" [3]="erv"..)
注意:bahs支持稀疏格式的数组
4.read -a ARRAY_NAME
[root@wen-7 shangkelianxi]# qwe=(1 2 4 5 67 8 9 ) [root@wen-7 shangkelianxi]# qwe[1]=1 [root@wen-7 shangkelianxi]# qwe=([1]=1 [2=]2 ) [root@wen-7 shangkelianxi]# read -a qwe 1 2 3 4 5
引用数组中的元素,${ARRAY_NAME[INDEX]}
注意:引用时,只给数组名,表示引用下标为0的元素;
[root@wen-7 shangkelianxi]# echo ${qwe[1]} 2 [root@wen-7 shangkelianxi]# echo ${qwe[2]} 3 [root@wen-7 shangkelianxi]# echo ${qwe} 1
数组的长度(数组中元素的个数)
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
[root@wen-7 shangkelianxi]# echo ${#qwe[@]} 5 [root@wen-7 shangkelianxi]# echo ${#qwe[*]} 5
引用数组中所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
[root@wen-7 shangkelianxi]# echo ${qwe[*]} 1 2 3 4 5 [root@wen-7 shangkelianxi]# echo ${qwe[@]} 1 2 3 4 5
数组元素切片:$ {ARRAY_NAME[@]:offset:number}
offset:要路过的元素个数
number:要去除的元素个数,省略number时,表示取偏移量之后的所有元素
[root@wen-7 shangkelianxi]# echo ${qwe[@]:2:3} 3 4 5 [root@wen-7 shangkelianxi]# echo ${qwe[@]:2:1} 3
向非稀疏数组中追加元素:
ARRAY_name[${ARRAY_name[*]}]=
删除数组中的元素
unset ARRAY[index]
[root@wen-7 shangkelianxi]# unset qwe[2] [root@wen-7 shangkelianxi]# echo ${qwe[2]}
关联数组
declare -A ARRAY_name
ARRAY_NAME=([index_name1]="value1" [index_name1]="value2")
[root@wen-7 shangkelianxi]# declare -A asd [root@wen-7 shangkelianxi]# asd=([a]="qwe" [b]="zc" [c]="fd1") [root@wen-7 shangkelianxi]# echo ${asd[a]} qwe [root@wen-7 shangkelianxi]# echo ${asd[b]} zc
实战:
1.生成10个随机数,并找出其中的最大值和最小值
declare -a rand declare -i max=0 declare -i min=99999 for i in {1..9};do rand[$i]=$RANDOM echo ${rand[$i]} [ ${rand[$i]} -gt $max ] && max=${rand[$i]} [ ${rand[$i]} -lt $min ] && min=${rand[$i]} done echo "max: $max min:$min"
2.定义一个数组,数组中的元素是/var/log目录下所有以.log结尾文件,统计其下标为偶数的文件中的行数之和
declare -a files files=(/var/log/*.log) declare -i lins=0 for i in $(seq 0 $[${#files[*]}-1]);do if [ $[$i%2] -eq 0 ]; then let lins+=$(wc -l ${files[$i]} | cut -d' ' -f1) fi done echo "lines:$lins"
3. 冒泡法,计算10个随机数,从大到小,从小到大排列
declare -i num; read -a arg -p "请输入10个数字:" for((i=0;i<=9;i++))do for((k=$[i+1];k<=9;k++))do if [ ${arg[$i]} -gt ${arg[$k]} ];then num=${arg[$i]} arg[$i]=${arg[$k]} arg[$k]=$num fi done done echo "正序排列${arg[*]}" echo "==============" for((i=0;i<=9;i++))do for((k=$[i+1];k<=9;k++))do if [ ${arg[$i]} -lt ${arg[$k]} ];then num=${arg[$i]} arg[$i]=${arg[$k]} arg[$k]=$num fi done done echo "逆序排列${arg[*]}"
字符串处理:
bash的内置字符串处理工具
字符串切片:
${var:offset:number}
取字符串的子串
[root@wen-7 shangkelianxi]# name=jerry [root@wen-7 shangkelianxi]# echo ${name:2} rry [root@wen-7 shangkelianxi]# echo ${name:2:2} rr
取字符串的最右侧的几个字符:${var: -length}
注意:冒号后必须有一个空白字符
[root@wen-7 shangkelianxi]# echo ${name: -4} erry
基于模式取子串:
${var#*word}:其中word是指定的分隔符,功能:自左而右,查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符.
${var##*word}:其中word是指定的分隔符,功能:自左而右,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符.
[root@wen-7 shangkelianxi]# myfa="/etc/init.d/functions" [root@wen-7 shangkelianxi]# echo ${myfa#*/} etc/init.d/functions [root@wen-7 shangkelianxi]# echo ${myfa##*/} functions
${var%word*}:其中word是指定的分隔符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符.
${var%%word*}:其中word是指定的分隔符,功能:自右而左,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符.
[root@wen-7 shangkelianxi]# myfa="/etc/init.d/functions" [root@wen-7 shangkelianxi]# echo ${myfa%/*} /etc/init.d [root@wen-7 shangkelianxi]# echo ${myfa%%/*} [root@wen-7 shangkelianxi]#mypath="/etc/init.d/funtion" ${mypath%*} /etc/init.d url=http://www.magedu.com:80 {url##*:} {url%%:*}
查找替换:
${var/PATTERN/SUBST}:查找var所代表的字符串中,第一次被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串
${var//PATTERN/SUBST}:查找var所代表的字符串中,所有被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串
${var/#PATTERN/SUBSTI}:查找var所代表的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串
${var/%PATTERN/SUBSTI}:查找var所代表的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串
[root@wen-7 ~]# user="root:x:0:0:root admin:/root:bin/chroot" [root@wen-7 ~]# echo ${user/root/ROOT} ROOT:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# echo ${user//root/ROOT} ROOT:x:0:0:ROOT admin:/ROOT:bin/chROOT [root@wen-7 ~]# echo ${user/#root/ROOT} ROOT:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# echo ${user/%root/ROOT} root:x:0:0:root admin:/root:bin/chROOT 注意:PATTERN中使用glob风格的通配符
查找删除:
${var/PATTERN}:以PATTERN为模式,查找var字符串中第一次的匹配,并删除值
${var//PATTERN}:以PATTERN为模式,查找var字符串中所有的匹配,并删除值
${var/#PATTERN}:以PATTERN为模式,查找var字符串中行首的匹配,并删除值
${var/%PATTERN}:以PATTERN为模式,查找var字符串中行尾的匹配,并删除值
[root@wen-7 shangkelianxi]# var=`getent passwd | grep ^root` [root@wen-7 shangkelianxi]# echo $var root:x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/root} :x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var//root} :x:0:0::/:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/#root} :x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/%bash} root:x:0:0:root:/root:/bin/
字符大小写转换:
${var^^}:把var中的所有小写字符转化为大写
${var,,}:把var中的所有大写字符转化为小写
[root@wen-7 shangkelianxi]# var=dfadfkladsnfkldshfkdf [root@wen-7 shangkelianxi]# echo ${var^^} DFADFKLADSNFKLDSHFKDF [root@wen-7 shangkelianxi]# var=AJDKFDAFKLDF [root@wen-7 shangkelianxi]# echo ${var,,} ajdkfdafkldf
变量赋值及引用:
变量赋值:
${var:-value}: 如果var变量为空,或未定义,那么返回value为值,否则,则返回var变量值
[root@wen-7 ~]# echo ${user:-qwe} root:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:-qwe} qwe
${var:=value}如果var变量为空,或未定义,那么返回value,并将value赋值给var变量,否则,则返回var变量值
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:=qwe} adfdf [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:=qwe} qwe
${var:+value}:如果var变量不空,则返回value为值.
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:+qwe} qwe
${var:?ERROR_INFO}:如果var变量为空,或未定义,则返回ERROR_INFO,否则,返回var的值
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:?error} adfdf [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:?error} -bash: user: error
为脚本程序使用配置文件,实现变量赋值(编写变亮脚本,多次引用)
(1) 定义文本文件,每行定义“ name=value”
(2) 在脚本中source此文件即可
[root@wen-7 shangkelianxi]# cat variable.sh #!/bin/bash declare -A qwe qwe=([a]="qas" [b]="zxc" ) declare -a asd asd=(1 2 3 5 4 6) declare -i sum=0 [root@wen-7 shangkelianxi]# cat variable1.sh #!/bin/bash source variable.sh echo ${qwe[a]} echo ${qwe[b]} echo $sum [root@wen-7 shangkelianxi]# bash variable1.sh qas zxc 4
变量高级用法-有类型变量
Shell变量一般是无类型的,但是bash Shell提供了declare和
typeset两个命令用于指定变量的类型,两个命令是完全等价的
declare [选项] 变量名
-r 将变量设置为只读属性
-i 将变量定义为整型数
-a 将变量定义为数组
-f 显示此脚本前定义过的所有函数名及其内容
-F 仅显示此脚本前定义过的所有函数名
-x 将变量声明为环境变量
-l 将变量值转为小写字母
-u 将变量值转为大写字母
间接变量引用:
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
variable1=variable2
variable2=value
variable1的值是variable2,而variable2又是变量名,
variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
bash Shell提供了两种格式实现间接变量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
[root@server ~]# N=NAME [root@server ~]# NAME=wangxiaochun [root@server ~]# N1=${!N} [root@server ~]# echo $N1 wangxiaochun [root@server ~]# eval N2=\$$A [root@server ~]# echo $2 wangxiaochun
eval命令:
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描
[root@server ~]# V1=pwd [root@server ~]# echo $V1 pwd [root@server ~]# eval $V1 /root
创建临时文件
mktemp命令:创建的临时文件可避免冲突
mktemp [OPTION]… [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出现三个
OPTION:
-d: 创建临时目录
–tmpdir=/DIR:指明临时文件所存放的目录位置
#mktemp --tmpdir=/testdir test.XXXXXX
安装复制文件
install命令:
install [OPTION]… [-T] SOURCE DEST 单文件
install [OPTION]… SOURCE… DIRECTORY
install [OPTION]… -t DIRECTORY SOURCE…
install [OPTION]… -d DIRECTORY…创建空目录
选项:
-m MODE,默认755
-o OWNER
-g GROUP
bash如何展开命令行
把命令行分成单个命令词
展开别名
展开大括号种的声明( {})
展开波浪符声明( ~)
命令替换$() 和 “)
再次把命令行分成命令词
展开文件通配( *、 ?、 [abc]等等)
准备I/0重导向( <、 >)
运行命令
防止扩展
反斜线( \)会使随后的字符按原意解释
$ echo Your cost: \$5.00
Your cost: $5.00
加引号来防止扩展
单引号( ’)防止所有扩展
双引号( ”)也防止所有扩展,但是以下情况例外:
$(美元符号) - 变量扩展
(反引号) - 命令替换
\(反斜线) - 禁止单个字符扩展
!(叹号) - 历史命令替换
配置文件:
两类:
profile类:为交互式登录的shell进程提供配置
bashrc类:为交互式登录的shell进程提供配置
登录类型:
交互式登录shell进程:
直接通过某终端输入账号密码后登录打开的shell进程
使用su命令,:su – uaername ;su -l Username 执行的登录切换
非交互式登录shell进程:
su username 执行的登录切换
图形界面下打开的终端
运行脚本
profile类:为交互式登录的shell进程提供配置
全局:对所有用户都生效
/etc/profile
/etc/profile.d/*.sh
局部:仅对当前用户生效
~/.bash_profile
功用:
用于定义环境变量
运行命令或脚本
bashrc类:
全局:
/etc/bashrc
局部:仅对当前用户生效
~/.bashrc
功用:
定义本地变量
冬衣命令别名
注意:仅管理员可修改全局配置文件
交互式登录shell进程:
/etc/profile–>/etc/profile.d/* –>~/.bash_profile–>~/.bashrc–>/etc/bashrc
非交互式登录shell进程:
~/.bashrc–>/etc/bashrc–>/etc/profile.d/*
命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
配置文件定义的特性,只对随后新启动的shell进程有效。
让通过配置文件定义的特性立即生效:
(1)用过命令重新定义一次;
(2)让shell进程重读配置文件
~]#source /path/TO/CONF_FILE
~]#./path/TO/CONF_FILE
问题:
1.如何定义对所有用户都生效的命令别名
在/etc/profile.d/中编写文件
2.让centos用户登录时,提供其已登录 并显示当前系统时间
[root@wen-7 ~]# vim /home/centos/.bash_login echo "hello $HOSTNAME" date
原创文章,作者:wencx,如若转载,请注明出处:http://www.178linux.com/39452