ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

shell编程进阶篇

2019-02-27 15:58:06  阅读:253  来源: 互联网

标签:file1 shell && 编程 arr 数组 echo 进阶篇 file


上一篇文章介绍的是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’ #打印清空成功

缺陷

  • 如果不是root用户不能执行进入/var/log ,和清空message文件
  • 不论是否成功下面的命令都继续执行
  • 不论脚本是否成功,都会输出‘clean 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)字符串测试操作符

  注意:在使用字符串进行比较时,最好使用””双引号将其扩起
shell编程进阶篇

(5)整数操作符

shell编程进阶篇

(6)逻辑操作符

shell编程进阶篇

(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,获得一个新的数组。

[root@test zy]# arr1=(1 2 3 4)
[root@test zy]# echo ${arr1[*]:0:2} #从下标为0开始取,取两个元素

数组的替换

语法:${arr[*]/valu1/valu2} #将数组中的某个值,替换成其他值(完全替换),生成新数组,数组本身不变。

[root@test zy]# arr1=(aa aa bb cc dd)
[root@test zy]# echo ${arr1[*]/aa/bb} #打印bb bb bb cc dd

数组的合并

语法:arr=(${arr1[*]} ${arr2[*]}) #arr1和arr2分别是两个数组

[root@test zy]# arr1=(1 2 3)
[root@test zy]# arr2=(4 5 6)
[root@test zy]# arr=(${arr1[]} ${arr2[]})
[root@test zy]# echo ${arr[*]} #打印:1 2 3 4 5 6

数组的遍历

#使用下标方式遍历:
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编程进阶篇

四、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()    #可以使用函数库中的函数

函数使用的注意事项
    - 在函数体中,位置参数($1、$2、$3、$#、$*、$@、$?)都可以是函数的参数
    - 父脚本的参数则临时的被函数参数所覆盖(相当于局部变量)
    - $0 仍然是父脚本的名称
    - return 关键字用于跳出函数
    - 函数调用不能在函数创建之前
    - 函数的返回值只能是数字,不然会报错 :numeric argument required

五、Shell脚本的调试

    - 调试自己写的脚本的方法有很多,这里小编送大家一张图:
shell编程进阶篇

标签:file1,shell,&&,编程,arr,数组,echo,进阶篇,file
来源: https://blog.51cto.com/14048416/2355609

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有