Shell脚本编程4
一、杂项知识整理
1、数组赋值方法:
declare -a files
files=(/var/log/*.log)通配所有文件也可
2、创建临时文件:
mktemp命令:创建的临时文件可避免冲突
mktemp NAME.XXXX(x至少要出现三个)
-d 创建临时目录
–tmpdir=/DIR 指明临时文件所存放的目录位置
[root@localhost tmp.X2wtb]# mktemp -d /testdir/tmp.XXXXX /testdir/tmp.yHrX9 [root@localhost tmp.X2wtb]# ll /testdir/tmp.* /testdir/tmp.X2wtb: 总用量 0 /testdir/tmp.yHrX9: 总用量 0
3、install命令:安装复制文件:
-m MODE 指定权限,默认为755
-o OWNER 指定所有者
-g GROUP 指定所属组
[root@localhost testdir]# install -m 770 -o root -g root -d tmpinstall [root@localhost testdir]# ll tmpinstall/ 总用量 0 [root@localhost testdir]# ll tmpinstall 总用量 0 [root@localhost testdir]# ll -d tmpinstall drwxrwx--- 2 root root 4096 8月 23 17:40 tmpinstall
4、bash如何展开命令行:
把命令行分成单个命令词
展开别名
展开大括号中的声明
展开波浪符声明
命令替换
再次把命令行分成命令词
展开文件通配
准备I/O重导向(<、>)
运行命令
5、bash的配置文件:按照生效范围划分,存在两类:
全局配置:/etc/profile、/etc/profile.d/*.sh、/etc/bashrc
个人配置:~/.bash_profile ~/.bashrc
shell登录的两种方式:
交互式登录:
直接通过终端输入账号密码登录
使用su – 切换用户
配置文件执行顺序:/etc/profile、/etc/profile.d/*.sh、~/.bash_profile、~/.bashrc、/etc/bashrc
非交互式登录:
su 登录
图形界面下打开的终端
执行脚本
执行顺序:~/.bashrc、/etc/bashrc、/etc/profile.d/*.sh
按照功能划分:profile类和bashrc类:
profile类:为交互式登录的shell提供配置
全局:/etc/profile、/etc/profile.d/*.sh
个人:~/.bash_profile
功能:用于定义环境变量;运行命令或脚本
bashrc类:为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用:定义命令别名和函数;定义本地变量
bash退出任务:保存在~/.bash_logout文件中(用户)
在退出登录shell时运行;
用于创建自动备份或者清除临时文件等。
二、命令详解及事例
1、数组:存储多个元素的连续的内存空间,相当于多个变量的集合。
索引:编号从0开始,属于数值索引;
注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0之后开始支持。
Bash的数组支持稀疏格式(索引不连续)
声明数组:
declare -a ARRAY_NAME
Declare -A ARRAY_NAME:关联数组
数组元素的赋值:
一次只赋值一个元素
ARRAY_NAME[INDEX]=NALUE
weekdays[0]=”sunday”
weekdays[4]=”thursday”
一次赋值全部元素
ARRAY_NAME=(“VAL1” ”VAL2” ”VAL3”…)
只赋值特定元素
ARRAY_NAME=([0]=”VAL1” [3]=”VAL2”…)
交互式赋值
命令:read -a ARRAY
引用数组元素:${ARRAY_NAME[INDEX]}
注意:省略[]表示引用下标为0的元素
数组的长度(数组中元素的个数):
${#ARRAY_NAME[*]} ${#ARRAY_NAME[@]}
示例:生成10个随机数保存于数组中,并找出最大值和最小值:
#!/bin/bash #array # declare -a RAND declare -i MAX=0 declare -i MIN=32766 for I in {0..9};do RAND[$I]=$RANDOM echo ${RAND[$I]} [ "${RAND[$I]}" -ge "$MAX" ] && MAX=${RAND[$I]} [ "${RAND[$I]}" -le "$MIN" ] && MIN=${RAND[$I]} done echo "MAX:$MAX" echo "MIN:$MIN"
写一个脚本,定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;
要统计其下标为偶数的文件中的行数之和:
#!/bin/bash #array # declare -a FILE declare -i LINE=0 FILE=(/var/log/*.log) for i in $(seq 0 $[${#FILE[@]}-1]);do if [ $[$i%2] -eq 0 ];then let LINE+=$(wc -l ${FILE[$I]} | cut -d" " -f1) fi done echo "Lines:$LINE"
2、数组数据处理:
引用数组中的元素:所有元素${ARRAY[@]},${ARRAY[*]}
数组切片:${ARRAY[@]:offset:number}
offset:要跳过的元素个数
number:要取出的元素个数
取偏移量之后的所有元素:${ARRAY:offset}
[root@localhost shelltest]# ing=(a b c d e) [root@localhost shelltest]# echo ${ing} a [root@localhost shelltest]# echo ${ing[3]} d [root@localhost shelltest]# echo ${ing[*]:2} c d e [root@localhost shelltest]# echo ${ing[*]:2:1} c
向数组中追加元素:
[root@localhost shelltest]# ing[${#ing[*]}]=f [root@localhost shelltest]# echo ${ing[5]} f
输出数组中的某单个元素:unset ARRAY[INDEX]
关联数组:declare -A ARRAY_NAME必须先声明
ARRAY_NAME=([idx_name1]=’val1’ [idx_name2]=’val2’…)
索引编号不是数字,自定义索引
[root@localhost shelltest]# declare -A jing [root@localhost shelltest]# jing=([a]=aaa [b]=bbb [c]=ccc) [root@localhost shelltest]# echo ${jing[c]} ccc [root@localhost shelltest]# echo ${jing[b]} bbb [root@localhost shelltest]# echo ${jing[a]} aaa
3、字符串处理:字符串切片:
${#var} 返回字符串变量var的长度;
${var:offset} 返回字符串var中从第offset个字符后(不包含)的字符开始,到最后的部分,offset的取值在0到${#var}-1之间(从bash4.2之后,允许为负值)。
${var:offset:number}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分。
${var: -lengh}:取字符串的最右侧几个字符。冒号后必须有一空白字符,如果不是用空白字符分隔,没有意义。例如:
[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var: -2} sf [root@localhost ~]# echo ${var: 5} jg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var:5} jg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var:5:12} jg21as4asd:a
基于模式取子串:${var#*word} 其中word可以是指定的任意字符
功能:自左而右,查找var变量所存储的字符串中,第一次出现的word,删除字符串开头至第一次出现word字符之间的所有字符。
${var##*word} 同上,不同的是:删除的是字符串开头至最后一次由word指定的字符之间的所有内容。例如:
[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var#*:} asdg1:asd:asdf:asf [root@localhost ~]# echo ${var##*:} asf
${var%word*} 其中word可以是指定的任意字符:
功能,自右往左,查找var变量存储的字符串中,第一次出现的word,删除字符串最后一个字符向左至第一次出现word字符之间的所有字符;例如:
[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var%:*} alasdjg21as4asd:asdg1:asd:asdf [root@localhost ~]# echo ${var%%:*} alasdjg21as4asd
查找替换:
${var/pattern/substi} 查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substi替换之。
${var//pattern/subti} 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substi替换之
${var/#pattern/substi} 查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substi替换之。
${var/%pattern/substi} 查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substi替换之。
[root@localhost ~]# echo ${var/:/@@} alasdjg21as4asd@@asdg1:asd:asdf:asf [root@localhost ~]# echo ${var//:/@@} alasdjg21as4asd@@asdg1@@asd@@asdf@@asf [root@localhost ~]# echo ${var/#@/vvv} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var/#:/vvv} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var/#/vvv} vvvalasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var/%/AAA} alasdjg21as4asd:asdg1:asd:asdf:asfAAA [root@localhost ~]# echo ${var/%asf/AAA} alasdjg21as4asd:asdg1:asd:asdf:AAA
查找并删除:
${var/pattern} 查找var所表示的字符串中,删除第一次被pattern所匹配到的字符串
${var//pattern} 删除所有匹配到的字符串
${var/#pattern} 删除行首被匹配到的字符串
${var/%pattern} 删除行尾被匹配到的字符串
${var^^} 把var中的所有小写字母转换为大写
${var,,} 把var中的所有大写字母转换为小写
例如:
[root@localhost ~]# echo $var alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var/%asf/AAA} alasdjg21as4asd:asdg1:asd:asdf:AAA [root@localhost ~]# echo ${var//as} aldjg214d:dg1:d:df:f [root@localhost ~]# echo ${var^^} ALASDJG21AS4ASD:ASDG1:ASD:ASDF:ASF [root@localhost ~]# echo ${a} root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${a/#*x} :0:0:root:/root:/bin/bash
pattern皆支持通配符,处理方式基于类似pattern space,不直接改变字符串。
变量赋值:
${var:-value} 如果为空或未设置,那么返回value;否则返回var值。
${var:+value} 如果var不空则返回value
${var:=value} 如果var为空或未设置,那么返回value,并将value赋值给var;否则则返回var的值;
${var:?error_info} 如果var为空或未设置,那么返回error_info;否则分会var的值。
[root@localhost ~]# echo ${var:-AAA} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var:+AAA} AAA [root@localhost ~]# echo ${var:=AAA} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${aaa:=AAA} AAA [root@localhost ~]# echo $aaa AAA [root@localhost ~]# echo ${va:?abc} -bash: va: abc [root@localhost ~]# echo ${var:?abc} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var:-AAA} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${var:+AAA} AAA [root@localhost ~]# echo ${var:=AAA} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# echo ${aaa:=AAA} AAA [root@localhost ~]# echo $aaa AAA [root@localhost ~]# echo ${va:?abc} -bash: va: abc [root@localhost ~]# echo ${var:?abc} alasdjg21as4asd:asdg1:asd:asdf:asf [root@localhost ~]# [root@localhost ~]#
给aaa赋值:若aaaa存在则赋aaaa的值,不存在则赋值123456
[root@localhost ~]# aaa=${aaaa:=123456} [root@localhost ~]# echo $aaa 123456
为脚本程序使用配置文件,实现变量赋值:
定义文本文件,每行定义NAME=VALUE;在脚本中source此文件即可。
4、declare命令:
-r 将变量设置为只读属性
-i 将变量定义为整型数
-a 将变量定义为数组
-f 显示此脚本前定义过的所有函数名及其内容
-F 仅显示此脚本前定义过的所有函数名
-x 将变量声明为环境变量
-l 将变量值转为小写字母
-u 将变量转为大写字母
[root@localhost ~]# declare -u a=aaa [root@localhost ~]# echo $a AAA
间接变量引用:如果第一个变量的值是第二个变量的名字,从第一个变量用用第二个变量的值就称为简介变量引用。bash中提供了两种格式实现间接变量引用:
eval tempvar=\$$variable1
eval命令:eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。
tempvar=${!variable1}
示例:
[root@localhost ~]# n=name [root@localhost ~]# name=wang [root@localhost ~]# NAME=${!n} [root@localhost ~]# echo $NAME wang [root@localhost ~]# eval NAME1=\$$n [root@localhost ~]# echo $NAME1 wang
eval命令示例:
[root@localhost ~]# abc=pwd [root@localhost ~]# eval $abc /root
三、课后练习
1、生成10个随机数,采用冒泡算法进行升序或降序排序。
#!/bin/bash #sort # read -p "ten number: " NUM if echo $NUM | grep [[:alpha:]] ;then echo "input right number!" exit 1 fi declare -a num=($NUM) declare -i min=0 echo ${num[@]} for I in `seq 0 $[${#num[@]}-1]`;do for J in `seq 1 $[${#num[@]}-1]`;do if [ ${num[$J]} -ge ${num[$[$J-1]]} ];then min=${num[$[$J-1]]} num[$J-1]=${num[$J]} num[$J]=$min fi done done echo ${num[@]}
原创文章,作者:SilencePavilion,如若转载,请注明出处:http://www.178linux.com/39295