读完学会shell语法,shell脚本80%已经学会
第3章 shell语法讲解
3.1 shell运算讲解
3.1.1 运算符的讲解
3.1.2 shell运算方式的讲解
3.1.2.1 $(())运算
[root@m01 test_init] # a=1
[root@m01 test_init] # b=1
[root@m01 test_init] # echo $a+$b
1+1
[root@m01 test_init] # echo $((c=a+b))
2
3.1.2.2. let运算(只能计算整数)
[root@m01 ~] # a=1
[root@m01 ~] # b=1
[root@m01 ~] # echo $d
[root@m01 ~] # let d=a+b
[root@m01 ~] # echo $d
2
[root@m01 ~] # a=1.5
[root@m01 ~] # let d=a+b
-bash: let: 1.5: syntax error: invalid arithmetic operator (error token is ".5")
[root@m01 ~] #
3.1.2.3 expr计算(expr只能计算整数,并且中间需要有空格)
[root@m01 ~] # a=1
[root@m01 ~] # b=4
[root@m01 ~] # expr c=a+b expr计算错误
c=a+b
[root@m01 ~] # expr c = a + b
expr: non-integer argument expr将a,b识别成参数,参数不是整数造成的
[root@m01 ~] # expr c =1+2
expr: syntax error expr语法错误
[root@m01 ~] # expr 1 + 2 expr正确的计算
3
[root@m01 ~] # expr 1 * 3 为什么这样计算也有问题
expr: syntax error
[root@m01 ~] # expr 1 \* 3 计算方式
3
3.1.2.3.1 expr乘法为什么需要将乘号转义下
- 原因:因为expr在计算的时候将*认成了通配符*造成的,使用echo则知道
3.1.2.3.2 expr 0+0的错误想法
- 问题:0+0=0,对的啊,为什么返回值是错误的
- 原因:我们可以在加一个数字来进行计算,会发现语法错误报错提示
- 结论:通过这个可以知道expr在计算的时候,不能是0和null
3.1.2.4 bc方法计算
3.1.2.4.1 整数计算
[root@m01 ~] # echo 3+2 | bc
5
[root@m01 ~] #
[root@m01 ~] # echo 5*3 | bc
15
[root@m01 ~] # echo 2^3|bc
8
[root@m01 ~] #
3.1.2.4.2 小数计算
- -l Define the standard math library.(定义标准数学计算方法)
[root@m01 ~] # echo "5/3" | bc
1 发现bc在计算的时候只会将整数输出来,默认小数不进行输出
[root@m01 ~] #
[root@m01 ~] #
[root@m01 ~] # echo "5/3" | bc -l
1.66666666666666666666
[root@m01 ~] #
[root@m01 ~] #
3.1.2.4.3 进制计算
[root@m01 ~] # echo "obase=16;1234"|bc 10进制转16进制
4D2
[root@m01 ~] # echo "obase=8;1234"|bc 10进制转8进制
2322
[root@m01 ~] # echo "obase=2;1234"|bc 10进制转2进制
10011010010
[root@m01 ~] # echo "obase=10;10000111"|bc 10进制转10进制(测试是不是输入的默认是10进制)
10000111
[root@m01 ~] # echo "obase=2;10000111"|bc 10进制转2进制
100110001001011011101111
3.1.2.5 awk计算方法
3.1.2.5.1 awk最普通的计算方法
[root@m01 ~] # awk 'BEGIN{print 3*2}'
6
[root@m01 ~] #
3.1.2.5.2 awk利用变量的计算方法
[root@m01 ~] # a=1
[root@m01 ~] # b=2
[root@m01 ~] # awk -v n=$b 'BEGIN{print n,n**3,n*n}'
2 8 4
[root@m01 ~] #
3.1.2.5.3 awk利用变量计算方法
[root@m01 ~] # a=1
[root@m01 ~] # b=2
[root@m01 ~] # awk -v n1=$a -v n2=$b 'BEGIN{print n1,n1**n2,n1*n2}'
1 1 2
[root@m01 ~] #
3.1.2.6 $[]计算方法
[root@m01 ~] # echo $((3/2))
1
[root@m01 ~] # echo $[3/2] 和(())一样,[]只是一对
1
3.2 shell条件测试语句的讲解
3.2.1 文件相关表达式
3.2.1.1 常见的表达式
表达式 | 含义 | 例子 |
-d | directory目录是否存在 | [root@m01 ~] # [root@m01 ~] # [ -d /oldboy/ ] && echo "true" || echo "false" true [root@m01 ~] # cd /oldboy [root@m01 oldboy] # |
-f | file文件是否存在 | [root@m01 oldboy] # [ -f /oldboy/1.txt ] && echo "true" || echo "false" true [root@m01 oldboy] # ll /oldboy/1.txt -rw-r--r-- 1 root root 12 Oct 1 11:50 /oldboy/1.txt [root@m01 oldboy] # |
-r | read文件是否存在,并且是否具有读权限 | [root@m01 ~] # [ -r /oldboy/bb ] && echo true || echo "false" false [root@m01 ~] # ll /oldboy/bb ls: cannot access /oldboy/bb: No such file or directory [root@m01 ~] # |
-w | write文件是否存在,并且是否具有写权限 | [root@m01 ~] # ll /oldboy/bb ls: cannot access /oldboy/bb: No such file or directory [root@m01 ~] # [ -w /oldboy/bb ] && echo true || echo "false" false |
-x | execute文件是否存在,并且是否具有执行权限 | [root@m01 ~] # ll /oldboy/bb ls: cannot access /oldboy/bb: No such file or directory [root@m01 ~] # [ -x /oldboy/bb ] && echo true || echo "false" false |
-s | size文件里面的内容是否是空的 | [root@m01 ~] # [ -s /oldboy/aa ] && echo true || echo "false" false [root@m01 ~] # cat /oldboy/aa [root@m01 ~] # |
-e | exits文件是否存在 | [root@m01 ~] # cat /oldboy/aa [root@m01 ~] # [ -e /oldboy/aa ] && echo true || echo "false" true [root@m01 ~] # |
-L | symlink文件是否存在,并且是不是软链接 | [root@m01 ~] # [ -L /etc/rc.local ] && echo true || echo "false" true [root@m01 ~] # ll /etc/rc.local lrwxrwxrwx 1 root root 13 Sep 20 11:25 /etc/rc.local -> rc.d/rc.local [root@m01 ~] # |
f1 -nt f2 | 文件f1是不是新于f2 | [root@m01 ~] # touch aa.txt [root@m01 ~] # touch bb.txt [root@m01 ~] # [ /root/aa.txt -nt /root/bb.txt ] && echo true || echo "false" false |
f1 -ot f2 | 文件f1是不是旧于f2 | [root@m01 ~] # touch aa.txt [root@m01 ~] # touch bb.txt [root@m01 ~] # [ /root/aa.txt -ot /root/bb.txt ] && echo true || echo "false" true |
3.2.2 字符串的比较(提示:字符串要加双引号"" )
表达式 | 含义 | 例子 |
-n | not zero字符串不是空的,则返回true | [root@m01 ~] # aa=0 [root@m01 ~] # [ -n "aa" ] && echo "$aa" || echo false 0 [root@m01 ~] # |
-z | zero字符串是空的,则返回true | [root@m01 ~] # aa=0 [root@m01 ~] # [ -z "aa" ] && echo "$aa" || echo false false |
"A"=="B" | 字符串A等于字符串B则返回true | [root@m01 ~] # aa=0 [root@m01 ~] # bb=2 [root@m01 ~] # [ "aa" == "bb" ] && echo "$aa" || echo false false |
"A"!="B" | 字符串A不等于字符串B,则返回true | [root@m01 ~] # aa=0 [root@m01 ~] # bb=2 [root@m01 ~] # [ "aa" != "bb" ] && echo "$aa" || echo false 0 [root@m01 ~] # |
3.2.3 整数的比较
3.2.3.1 []比较
表达式 | 含义 | 例子 |
-gt | greate than大于 | [root@m01 ~] # [ 3 -gt 2 ] && echo yes || echo no yes |
-ge |
greate equal 大于等于 | [root@m01 ~] # [ 3 -ge 3 ] && echo yes || echo no yes [root@m01 ~] # |
-lt |
less than 小于 | [root@m01 ~] # [ 3 -lt 2 ] && echo yes || echo no no [root@m01 ~] # |
-le |
less equal 小于等于 | [root@m01 ~] # [ 3 -le 2 ] && echo yes || echo no no [root@m01 ~] # |
-ne |
not equal 不等于 | [root@m01 ~] # [ 3 -ne 2 ] && echo yes || echo no yes [root@m01 ~] # |
-eq |
equal 等于 | [root@m01 ~] # [ 3 -eq 4 ] && echo yes || echo no no |
3.2.3.2 (())或者[[]]比较(不常用)
表达式 | 含义 | 例子 |
> | 大于 | [root@m01 ~] # ((3>2)) && echo yes || echo no yes |
>= |
大于等于 | [root@m01 ~] # ((2>=3)) && echo yes || echo no no |
< |
小于 | [root@m01 ~] # ((3<2)) && echo yes || echo no no [root@m01 ~] # |
<= |
小于等于 | [root@m01 ~] # ((2<=2)) && echo yes || echo no yes [root@m01 ~] # |
!= |
不等于 | [root@m01 ~] # ((2!=2)) && echo yes || echo no no [root@m01 ~] # |
== or = |
等于 | [root@m01 ~] # ((2==2)) && echo yes || echo no yes [root@m01 ~] # |
3.2.4 逻辑符号的比较
3.2.4.1 []比较方法
表达式 | 含义 | 例子 | (())比较方法 |
! |
not取反 | [root@m01 ~] # [ ! -d /etc/aa ] && echo "yes" || echo "no" yes [root@m01 ~] # |
! |
-a |
and并且的关系 | [root@m01 ~] # [ ! -d /etc/aa -a -f /etc/hosts ] && echo "yes" || echo "no" yes [root@m01 ~] # |
&& |
-o |
or或者的关系 | [root@m01 ~] # [ -d /etc/aa -o -f /etc/host ] && echo "yes" || echo "no" no [root@m01 ~] # |
|| |
3.3 if语句的讲解
3.3.1 if语句的语法
3.3.1.1 单分支结构
3.3.1.1.1 语法
if [ ];then
命令
fi
if [ ]
then
命令
fi
3.3.1.1.2 例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
if [ 3 -gt 2 ]
then
echo "true"
fi
[root@m01 test_init] # sh para_0.sh
true
[root@m01 test_init] #
3.3.1.2 双分支结构
3.3.1.2.1 语法
if [ ]
then
echo cmd1
else
echo cmd2
fi
3.3.1.2.2 例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
if [ 3 -lt 2 ]
then
echo "true"
else
echo "false"
fi
[root@m01 test_init] # sh para_0.sh
false
[root@m01 test_init] #
3.3.1.3 多分枝结构
3.3.1.3.1 语法
if []
then
echo ""
elif []
then
echo ""
else
echo ""
fi
3.3.1.3.2 例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
read -p "please input num " num
if [ $num -lt 2 ]
then
echo "true"
elif [ $num -lt 10 ]
then
echo "el_true"
else
echo "false"
fi
[root@m01 test_init] # sh para_0.sh
please input num 12
false
[root@m01 test_init] # sh para_0.sh
please input num 9
el_true
[root@m01 test_init] #
3.4 while语句的讲解
3.4.1 语法讲解
3.4.1.1 有限的循环
while <条件表达式>
do
命令1
done
3.4.1.2 无限的循环
[root@m01 test_init] # while true
do
条件
done
3.4.1.3 while读取的方法
[root@m01 test_init] # while read 变量
do
echo ""
done<文件
3.4.2 例子
3.4.2.1 有限循环的例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
a=$1
while [ $a -lt 2 ]
do
echo "aa"
let a++;
done
[root@m01 test_init] # sh para_0.sh 0
aa
aa
[root@m01 test_init] #
3.4.2.2 无限循环的例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
while true
do
echo "aa"
done
[root@m01 test_init] #
3.4.2.3 read的例子(暴力破解超过10次就给禁止掉)
[root@m01 test_shell] # vim pojie_ip.sh
#!/bin/bash
file_txt=/server/scripts/count.txt
awk '$6~/Failed/{print $(NF-3)}' /var/log/secure | sort -nr | uniq -c > $file_txt
while read key value
do
if [ $key -gt 10 -a `iptables -nvL | grep -wc "$value"` -eq 0 ]
then
iptables -A INPUT -s $value -p tcp --dport 22 -j DROP
fi
done<$file_txt
3.5 case语句的讲解
3.5.1 case语法讲解
case "变量" in
值1)
指令1...
;;
值2)
指令2...
;;
*)
指令3...
esac
case "你有什么条件" in
有钱)
白富美结婚
;;
有权)
白富美结婚
;;
有爹)
白富美
;;
有才有能力有潜力)
先谈个对象看看
;;
*)
洗洗睡吧
esac
3.5.2 case例子讲解
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
read -p "please input num " num
case $num in
1) echo "you input num is 1" ;;
2) echo "you input num is 2" ;;
*) echo "you input num null " ;;
esac
[root@m01 test_init] # sh para_0.sh
please input num 2
you input num is 2
[root@m01 test_init] # sh para_0.sh 6
please input num 6
you input num null
[root@m01 test_init] #
3.6 函数的讲解
3.6.1 函数的概念
将程序中经常能使用的代码组合起来,并且起个函数名称
3.6.2 函数的语法格式
function 函数名() {
指令集
return n
}
function 函数名 {
指令集
return n
}
函数名() {
指令集
return n
}
3.6.3 函数的例子
3.6.3.1 函数通常使用
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
fun() {
aa=12
echo $aa
}
fun
[root@m01 test_init] # sh para_0.sh
12
[root@m01 test_init] #
3.6.3.2 函数传参方式使用
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
a1=$1
echo $a1
fun() {
aa=$2
echo $2
}
fun
[root@m01 test_init] # sh para_0.sh 1 2 2个参数为啥只识别了脚本里面的,函数里面的没有
1
[root@m01 test_init] #
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
a1=$1
echo $a1
fun() {
a2=$1
echo $a2
}
fun 66
[root@m01 test_init] # sh para_0.sh 1 发现2个参数都已经出来了
1
66
[root@m01 test_init] #
- 结论:函数里面的参数信息和shell里面的参数信息是不一致的,函数里面的信息只对函数本身起作用,属于局部的,shell里面的参数信息是全局的,整个shell都可以使用
3.7 颜色和vimrc的讲解
3.7.1 颜色的语法
\e[字体格式;颜色 文字信息\e[0m
\033[字体格式;颜色 文字信息\033[0m
\E[字体格式;颜色 文字信息\E[0m
3.7.2 颜色的例子
3.7.3 对每个组成进行讲解
- \e也可以使用\033替代。
- [1数字1表示加粗显示(这个位置可以加不同的数字代表不同的意思,详细信息可man console_codes获得) 。
- 31m表示为红色字体,这个位置可以换不同的数字,以代表不同的意思。
- "aa":表示待设置的内容。
- [0m表示关闭所有属性,这个位置可以换不同的数字,以代表不同的意思
man console_codes
3.7.4 vimrc的讲解
- 当前用户生效~/.vimrc
- 全部用户生效/etc/vimrc
3.8 for语句的讲解
3.8.1 for语法格式
for 变量 in 变量取值的列表
do
指令
done
for 变量 in 1 2 3 4 5 {a..z} `seq 10` `ls /etc`
do
指令
done
C循环使用
for((i=1;i<=10;i++)) 只是用来对数字进行循环,给shell数组进行循环
do
指令
done
3.8.2 for的例子
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
for i in `seq 10`
do
echo $i
done
[root@m01 test_init] # sh para_0.sh
1
2
3
4
5
6
7
8
9
10
[root@m01 test_init] #
[root@m01 test_init] # cat para_0.sh
#!/bin/bash
n=0
sum=0
for i in `seq 10`
do
((sum=sum+i))
done
echo $sum
[root@m01 test_init] # sh para_0.sh
55
[root@m01 test_init] #
3.8.3 循环控制
名称 | 含义 | 例子 |
continue (n) | 终止本次循环,开始下一次的循环,n表示结束本次循环,直接跳到第n次循环 | [root@m01 test_init] # vim para_0.sh
#!/bin/bash
for i in `seq 10` do for j in `seq 10` do if [ $j -eq 6 ] && continue 2 then echo $j else echo $i $j fi done done |
break (n) | 终止这次循环并且以后的循环,直接跳出,n表示结束循环,调到指定的n次循环 | [root@m01 test_init] # vim para_0.sh #!/bin/bash
for i in `seq 10` do for j in `seq 10` do for k in `seq 10` do [ $k -eq 6 ] && break 2 echo $i $j $k done done done |
exit n | 退出脚本,n返回值 | [root@m01 test_init] # cat para_0.sh #!/bin/bash
for i in `seq 10` do if [ $i -eq 9 ] then exit 0 fi done [root@m01 test_init] # echo $? 0 [root@m01 test_init] # |
return n | 返回数值,n放在脚本或者函数的最后,判断函数的返回值 | [root@m01 test_init] # vim para_0.sh #!/bin/bash
fun() { for i in `seq 10` do if [ $i -eq 9 ] then return 0 fi done } fun |
3.9 shell数组讲解
3.9.1 语法
3.9.1.1 通过[]方式来获取
[root@m01 ~] # ip[1]=10.0.0.61
[root@m01 ~] # ip[2]=10.0.0.51
[root@m01 ~] # ip[3]=10.0.0.41
[root@m01 ~] # echo ${#ip[*]}
3
[root@m01 ~] # echo ${ip[*]}
10.0.0.61 10.0.0.51 10.0.0.41
[root@m01 ~] #
3.9.1.2 通过()方式来获取
[root@m01 ~] # ip=(10.0.0.61 10.0.0.51 10.0.0.41)
[root@m01 ~] # echo ${ip[*]}
10.0.0.61 10.0.0.51 10.0.0.41
[root@m01 ~] # echo ${ip[0]}
10.0.0.61
[root@m01 ~] #
[root@m01 ~] # ip=(`cat /etc/hosts`)
[root@m01 ~] # echo ${ip[*]}
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.16.1.81 firewalld 172.16.1.5 lb01 172.16.1.6 lb02 172.16.1.7 web01 www.oldboy.com 172.16.1.8 web02 172.16.1.9 web03 172.16.1.51 db01 172.16.1.31 nfs01 172.16.1.41 backup 172.16.1.61 m01 172.16.1.71 zabbix
[root@m01 ~] # echo ${#ip[*]}
33
[root@m01 ~] #
3.9.2 例子
[root@m01 ~] # ip=(10.0.0.61 10.0.0.51 10.0.0.41)
[root@m01 ~] # for i in ${ip[*]} ;do ping -c 1 -W1 $i ;done