shell编程进阶篇
上一篇文章介绍的是shell的基础知识:
https://blog.51cto.com/14048416/2355550
??有人会说,shell简单啊,就是一些命令的堆砌啊,是的一些简单的操作仅仅执行几个命令就行了,但是相对一些复杂的业务和要求下,如果只能做到命令的堆砌,那也太有损shell的名声了。 ??小编通过一个例子给大家介绍,如果没有逻辑和条件,只是命令的堆砌,那么对维护Linux,是多么大的灾难。 #需求:清除/var/log 下message 日志文件 #!/bin/bash #shell 脚本的标识 cd /var/log #进入/var/log cat /dev/null > message #清空message日志 echo Logs cleaned up’ #打印清空成功 缺陷:
修改后的脚本: #!/bin/bash #shell 脚本的标识 LOG_DIR=/tmp/log #设置一个变量,名称为/tmp/log ROOT_UID=$UID #设置一个变量为当前的用户的uid if [ "$UID" -ne 0 ] #判断是否是root,root用户的uid为0 then echo "Must be root tu run this script" #如果不是输出,并异常退出脚本 exit 1 fi cd $LOG_DIR || { #如果是root,在判断是否可以进入/tmp/log echo "Cannot change to necessary directory." >&2 #如果不能进入,则也异常退出 exit 1 } cat /dev/null>message && echo "Log clean up." #最后清空之后,输出一句话并正常退出 exit 0 有些初学者,看见上面的脚本,可能觉得,有些看不懂,没关系,接下来,小编将会一一讲解上面脚本的知识点! 一、条件测试??在bash的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同的操作,有时候也会通过if流程控制语句相结合,使我们可以方便的完成判断。 格式1:test<测试表达式> 格式2:[ 测试表达式 ] 格式3:[[测试表达式]] 提示:在[[]]中,可以使用&&、||、>、<等操作符进行复杂判断,但是不能应用于[] (1)test条件测试#使用方法: test -f file 判断是否是文件 例:test -f file && echo 1 || echo 0 #判断文件是否存在,存在返回 1 不存在返回0 test ! -f file 判断文件是否不存在 例:test !-f file && echo 1 || echo 0 #判断文件是否存在,不存在返回1 存在返回0 test -d dir 判断是否是目录 (2)[]条件测试#使用方法: [-f file] 普通文件是否存在 例:[-f file ] && echo 1 || echo 0 #判断文件是否存在,存在返回 1 不存在返回0 [ ! -f file ] 判断文件是否不存在 例:[-f file] && echo 1 || echo 0 #判断文件是否存在,不存在返回1 存在返回0 [-d dir] #判断是否是目录 -s # 判断文件是否存在并且不为空 -e #判断文件是否存在,区别于-f,-e表示所有文件 -r #判断文件是否存在并且是否可读 -w #判断文件是否存在并且是否可写 -x #判断文件是否存在并且是否可执行 -L #判断文件是否存在并且是否为链接文件 f1 -nt f2 #判断是否f1比f2新 f1 -ot f2 #判断是否f1比f2久 (3)[[]]条件测试#使用方法: [[-f file]] 文件是否存在 例:[[-f file ]] && echo 1 || echo 0 #判断文件是否存在,存在返回 1 不存在返回0 [[ ! -f file ]] 判断文件是否不存在 例:[[-f file]] && echo 1 || echo 0 #判断文件是否存在,不存在返回1 存在返回0 (4)字符串测试操作符??注意:在使用字符串进行比较时,最好使用””双引号将其扩起 (5)整数操作符(6)逻辑操作符(7)条件测试的举例??上面讲了诸多概念,现在通过具体的例子让大家看看条件测试具体怎么用: #这里声明两个变量:file1=/etc/password file2=/etc/service [-f “$file1”] && echo 1||echo 0 $file1存在返回1,不存在返回0 [-d “$file1”] && echo 1||echo 0 $file1是目录返回1,不是目录返回0 [-s “$file1”] && echo 1||echo 0 $file1是文件并且不为空返回1,否则返回0 [-e “$file1”] && echo 1||echo 0 $file1存在返回1,不存在返回0 [-w “$file1”]&&echo 1 ||echo 0 $file1存在并且可写,返回1,不存在返回0 [-x “file1”]|| exit 5 判断$file1是否可执行,不可执行异常退出 #对字符串的操作 [-z “$value”] || value=”…” 判断变量是否长度为0,如果为0,赋初值 [“$networkworking”!= “yes”]&&exit 6 通过对变量的判断,确定是否执行脚本后面的代码 #复合条件测试 [-f “$file1”-o -e “$file2”] &&echo 1 ||echo 0 file1是文件或者file2存在返回1,否则0 [-f “$file1”-a -e “$file2”] &&echo 1 ||echo 0 file1是文件并且file2存在返回1,否则0 [[-f “$file1”&& -e “$file2”]] &&echo 1 ||echo 0 file1是文件或者file2存在返回1,否则0 [[-f “$file1”|| -e “$file2”]] &&echo 1 ||echo 0 file1是文件并且file2存在返回1,否则0 #整数测试 [ 1 -eq 2 ] &&echo 1||echo 0 等于 [ 1 -gt 2 ] &&echo 1||echo 0 大于 [ 1 -lt 2 ] &&echo 1||echo 0 小于 [ 1 -le 2 ] &&echo 1||echo 0 小于等于 [ 1 -ge 2 ] &&echo 1||echo 0 大于等于 [ 1 -ne 2 ] &&echo 1||echo 0 不等于 注意:及时这里的两个数组都是字符串的形式,依然可以比较。 #判断条件后面执行多条命令 file=/etc/profile file_bak=${file}.bak [ -f $file ] && { cat $file cp $file $file_bak mv $file_bak ~/ } 二、控制流程语句?? 当然,仅仅学习了条件测试,就可以完成很多的功能,但是如果业务相当复杂,功能相当繁多,只是使用条件测试话,不仅完不成具体的功能,对代码的可读性也很差。为了胜任更高的要求,接下来介绍控制流程语句,可以说shell有了它,如鱼得水吧。 (1)if语句单分支 #语法: If [条件] then 命令; 命令; …. fi 或者:if[条件];then 命令…; fi #例:比较大小 num1=10 num2=23 if [ $num1 -gt $num2 ] then echo "$num1" else echo "$num2" fi #判断系统内存大小,如果小于100M就报警 cur_free=`free -m|awk ‘ /buffers// {print $NF}‘` chars="current memory is $cur_free" if [ $cur_free -lt 100 ] then echo "$chars" echo "momory is unfree!" fi 多分支 #语法: 多分支: If [条件] then 命令; 命令; …. else 命令; 命令; …. fi #例:判断文件是否存在,不存在就创建 file=/tmp/zy/zy.txt if [ -f "$file" ] then ll $file else touch $file fi if-elif-elif...-else: if [条件] then 命令; 命令; elif [条件] then 命令 else 命令 fi #例:比较两个数的大小 read -p "pls input two numbers:" a b if [ $a -gt $b ] then echo "$a > $b" elif [ $a -eq $b ] then echo "$a == $b" else echo "$a < $b" fi (2)case语句#语法: case: 语法: case “字符串变量”in pat1) 指令;; pat2) 指令;; pat3) 指令;; *)指令 ;; esac #例: read -p "Please you input is a num:" num case "$num" in 9[0-9]) #范围查找 echo A;; 8[0-9]) echo B;; *) echo C;; esac (3)for循环for 循环,具体的使用方法有很多,这里我们使用三个例子说明: #例1:(命令作为循环内容) for i in `seq 10` do echo $i done #例2:(序列作为循环内容) sum=0 for i in {1..100} do let sum=sum+i done echo $sum #例3:(集合算术操作符的for) sum=0 for((i=1;i<=100;i++)) do let sum=sum+i done echo $sum (3)while循环#语法 while [expression] do 指令 done #举例: #例1 i=1 sum=0 while ((i<=100)) do let sum=sum+i let i++ done echo $sum #例2 i=1 sum=0 while [ $i -le 100 ] do let sum=sum+i let i++ done echo $sum (4)until循环#语法 unitl [ expression] do commond; done #举例: sum=0 i=1 until [ $i -gt 100 ] do let sum=sum+i let i++ done echo $sum 注意:unit和for、while的区别就是,until是条件满足时退出循环,而while和for是条件不满足是退出循环。 三、shell中的数组(1)数组的定义:方法1:array=(value1 value2 valu3 value4) 方法2:array=([index1]=value1 [index2]=value2 [index3]=value3) 方法3:array[0]=value1 array[1]=value2 array[2]=value 方法4:使用命令的方式定义数组:array=($(ls)) 将ls命令的执行结果当做数组的值 (2)数组的增、删、改、查arr=(1 2 3 4 5 6 7) #数组的声明,并赋值 #增 arr[index]=value #给数组增加元素,index:下标(任意) #删 unset arr[index] #删除相应index位置的元素 unset arr #删除整个数组 #改 arr[index]=value #给数组增加元素,index:下标(该位置已存在值) #查: echo ${arr[index]} #获取数组单个元素,index表示数组的下标 echo ${arr[*]} #获取数组的所有元素 echo ${arr[@]} #获取数组的所有元素 echo ${!arr[*]} #获取数组的所有下标 echo ${#arr[@]} #查看数组的长度 (3)数组的高级操作数组内容的截取? 语法:${arr[*]:number1:len} 从下标number1开始取,取长度为len,获得一个新的数组。
数组的替换? 语法:${arr[*]/valu1/valu2} #将数组中的某个值,替换成其他值(完全替换),生成新数组,数组本身不变。
数组的合并? 语法:arr=(${arr1[*]} ${arr2[*]}) #arr1和arr2分别是两个数组
数组的遍历#使用下标方式遍历: arr=(1 2 3 4 5 6) for i in “${!arr[*]}” do echo “${arr[$i]}” done #使用数组的值遍历 for i in “${arr[*]}” do echo “$i” done (4)数组的存储注意:Shell中的数组的存储方式不同,如果在相应的下标中无元素,则无此下标。 四、Shell中的函数?语法 #简答语法: 函数名(){ 指令… return n } #标准语法 function 函数名(){ 指令… return n } ?shell函数的执行 #例子 #!/bin/sh #无参数 function func_test1(){ return 2 } #有参数 function func_test2(){ let sum=$1+$2 #这里的$1和$2暂时作为函数的参数 return $sum } #调用参数函数 func_test1 echo "$?" #调用有参数的函数 func_test2 1 2 echo "$?" #$?用于接受函数的返回值 ?自定义函数库 #第一步:编写一个脚本(函数库): #!/bin/sh function func1(){…} function func2(){…} function func3(){…} #第二步:(在其他脚本中加载这个函数库) #!/bin/sh source ./函数库名 #下载函数库 func1() #可以使用函数库中的函数 ?函数使用的注意事项: 五、Shell脚本的调试? ? - 调试自己写的脚本的方法有很多,这里小编送大家一张图: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |