shell中级部分总结

数组

定义数组IPS=(192.168.2.1 192.168.2.2 192.168.2.3)  #空格隔开,不能用逗号隔开​[root@lianxi ~]# echo $IPS  #默认为数组第一个192.168.2.11.显示数组所有元素    [root@lianxi ~]# echo ${IPS[@]}    192.168.2.1 192.168.2.2 192.168.2.32.显示数组元素个数    [root@lianxi ~]# echo ${#IPS[@]}    3    [root@lianxi ~]# echo ${#IPS[1]} #第一个元素的个数    11​3.显示数组的某一个元素    [root@lianxi ~]# echo ${IPS[1]}  #下标从0开始    192.168.2.2

转义和引用

特殊符号

# 注释 ; 分号 分割两个命令的\ 转移符号 \n \t \r 和 \$ \" \\ "不完全引用"和'完全引用,所见即所得'和``

运算符

在shell用用的非常少,性能不高

  • 赋值运算符

    =用于算数和字符串赋值,使用unset取消;算符运算符有

  • 算数运算符 + - * / ** % 或者 expr 4+5 expr只支持整数类型计算,不支持浮点数;

    [root@lianxi ~]# expr 4+5 #+号两边没空格,则当成字符串了4+5[root@lianxi ~]# expr 4 + 5  #可以支持加减乘除等等,只能是整数计算,并且得到的也是整数9​[root@lianxi ~]# numb=`expr 4 + 5` #注意是反引号,这样将计算结果赋值给变量;​

     

  • 数字常量 let “变量名=变量值”,使用0开头的为八进制,0x开头的为十六进制;直接将计算的值赋值给变量就用let

    let a=4+5,shell中很少用let,使用下面双括号更方便

  • 双圆括号

    ((a=10)) 或者((a=4+5))或者((a++))或者echo $((4+5))或者 a=$((4+5))

变量运算

1整数运算,expr $(()),$[],不支持小数运算

[root@web01 ~]# expr 5 + 4   +边一定要有空格,9[root@web01 ~]# echo $((5+4))9[root@web01 ~]# echo $[ 4 + 5 ]9​如果有小数,就需要用到bc或者awk也可以awk 'BEGIN{print 5/2}'

特殊符号大全

  • 引号

    "",'',``
  • 括号

    (),(()),$()单独使用圆括号会产生一个子shell(xyz=123)数组初始化IPS=(ip1 ip2 ip3)$()和``都是取值的let的简写就是(())​​[],[[]]单独使用方括号是测试(test)或数组元素功能,test的简写两个方括号表示测试表达式;这组符号与先前的 [] 符号,基本上作用相同,但她允许在其中直接使用 || 与&& 逻辑等符号。​​< > 数值比较 单独一个就是重定向符号​{}输出范围 echo {1..9}文件复制 cp /etc/passwd{,.bak}
  • 运算和逻辑符号

    (( 5 > 4  && 6 < 8 )) #两个判断都为真,则为真,$?(( 5 > 4  || 6 > 8 )) #只要有个为真,则为真(( ! 5 > 4 )) 
  • 转义符号

  • 其他符号

    分号;分隔命令ifdown eth0 ; ifup eth0 使用分号是将两个命令一起传递给主机,比&&符号强,更比分开执行强;在case语句中使用两个;;对分号进行转义,或者在if [] ;then 写在同一行,分隔命令,显示更加整洁: 占位符,相当于passls *.sh 和 ls ?.sh​

完全路径执行

定义个sh,然后赋予x权限,使用绝对路径去执行[root@lianxi ~]# vim /tmp/9.shif [ $USER = root ];then    echo "user root"else    echo "other user"fi[root@lianxi ~]# /tmp/9.sh  #绝对路径去执行作者回复: /tmp/9.sh完整路径运行相当于外部命令,  这种相当于执行了一个bash命令,然后把9.sh里的每条语句运行一次,然后执行exit

if

if和case都是流程控制语句;

#判断当前用户是否为root用户[root@lianxi ~]# [ $UID = 0 ] #这里的0是字符串类型,等同于[ $UID = '0' ][root@lianxi ~]# [ $UID -eq 0 ] #这里的0是数值类型 [root@lianxi ~]# [ $USER = root ] #这里值字符串判断在shell里面即使以数字0-9方式使用,变量仍然当做字符串处理,UID是系统定义好的变量,一定是整数,所以这里用= 或者 -eq 都可以实现判断用户id的功能​​if后面还可以跟命令[root@lianxi ~]# cat 1.sh #/bin/bashif pwd;then  #pwd命令一定会执行成功,所以返回值为0,继续往后执行    echo "hello"fi[root@lianxi ~]# bash 1.sh /roothello​​如果传入的变量有个特殊字符,就用""阔起来 [ "$pos" = "help" ] if [] ;thenelsefi​if [];thenelif [];thenelsefi###########################if grep $1 /etc/paswd;thenecho "这里也是可以的,你需要弄清楚"fi​​#取反if [ ! 5 -lt 3 ];then  #叹号一定要搞清楚!​-r -w -x只要user,group,other其中一个人有对应的权限就为真!​三元表达式[ -d /test ] && {echo "yes"} || {echo "NO.."}  #和if..else是一样的效果! 

还有if..else,if嵌套等等;

如果输入1或者backup都是退出,那么通过if是无法进行判断的,这时候就需要用到了case,

case可以进行多条件进行判断

CASE

case可以通过if来实现,但是case更加方便;

case "$变量" in    "情况1")        命令..;;    "情况2")        命令..;;    *)        命令;;esac​我们在systemctl start,stop,restart,disabled等等就是用的case实现的;​case "$1" in     三个选项执行同样的结果,这种复杂判断,只能用case进行!    1|'start'|'START')   # | 不要包含在里面,要不然会被当做一个整体,所以分出来!!!!    echo "start....."    ;;    'stop'|'STOP')    echo "stop...."    ;;    *)    echo "Usage: $0 {start|stop}"    ;;esac​

case可以嵌套,还可以在每个选项中进行if判断!

颜色输出

source /etc/init.d/functions#就是将echo 变为actionaction "成功" /bin/true action "失败"  /bin/false

正则匹配

正则匹配一定要在双括号中使用[[]],单括号是无法进行正则匹配的

判断用户输入的数据必须是数字read -p "Please input you number:" ret[[  $ret =~ ^[0-9]+$ ]] || { echo "必须输入数字才可以!" ; exit; } #加上{}意义就不一样了,表示这两个为一个整体​

for循环语法

for 变量 in [ 取值列表 ]do    循环体done​for var in a1 a2 a3 a4 ...do;done​str="192.168.1.1 192.168.1.2 192.168.1.3" #后面这些是字符串,但是for循环能够根据空格分割他们虽然后面是一个字符串,但是for循环依然能够循环他们,根据空格分割;换成其他符号就不行了!for i in $str;doecho $idone​​列表生成:{1..9}for 参数 in 列表 #这是列表,如果想控制循环次数,看下面的for语句do​done ​使用反引号或者$()方式,命令的执行结果当做列表进行处理,for i in {1..100}这是可以的for i in {1..$(ls -l|wc -l)} 这中后面当做字符串了,所以无法执行;+ for i in '{1..$(ls -l|wc -l)}'+ echo '{1..6}'{1..6}

使用反引号或者$()方式,命令的执行结果当做列表进行处理;按空格分割!

for循环自定义分隔符

默认情况下空格作为分隔符,通过IFS来自定义分隔符

[root@web01 ~]# cat /etc/hosts127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4::1         localhost localhost.localdomain localhost6 localhost6.localdomain6[root@web01 ~]# cat 1.sh for i in `cat /etc/hosts`;do    echo $idone[root@web01 ~]# bash 1.sh 127.0.0.1localhostlocalhost.localdomainlocalhost4localhost4.localdomain4::1localhostlocalhost.localdomainlocalhost6localhost6.localdomain6​可以看到每一行都取出来后,然后按空格分隔成列表;如果想每一行为一个单位输出怎么办?​#以冒号最为分隔符  IFS=:#以冒号\分号和双引号作为字段分隔符 IFS=;:"#以换行符作为字段分割符   IFS=$'\n'​[root@web01 ~]# cat 1.sh #!/bin/bashIFS=$'\n'for i in `cat /etc/hosts`;do    echo $idone[root@web01 ~]# bash 1.sh 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4::1         localhost localhost.localdomain localhost6 localhost6.localdomain6​这样就能满足要求了!​​for i in $(cat /etc/passwd);do    echo $i | grep "root"  #过滤出root的行    grep "root" $i  #这种写法是错的!!!他把$i当做文件名了!!!!!!!!!!!!!!!!!!!!所以错了!!done

请登录后发表评论

    没有回复内容