Linux7.6—Shell编程 学习笔记 第三章:Shell高级进阶
Linux7.6—Shell编程
第三章:Shell高级进阶
一.Shell运算符
1.1.算数运算符
| 运算符 | 说明 | 举例(a=10,b=20) |
|---|---|---|
| + | 加 | expr $a + $b结果为30 |
| - | 减 | expr $a + $b结果为-10 |
| * | 乘 | expr $a + $b结果为200 |
| / | 除 | expr $a + $b结果为2 |
| % | 取余 | expr $a + $b结果为0 |
| = | 赋值 | a=$b将把变量b的值赋给a |
| == | 相等,比较两端数值是否相等,相等返回ture | $a == $b返回false |
| != | 不等,比较两端数值是否相等,不等返回ture | $a != $b返回true |
#!/bin/bash
a=10
b=20
num=`expr $a + $b`#或者num=$(expr $a + $b)
echo "a + b = $num"
num=`expr $a - $b`
echo "a - b = $num"
num=`expr $a \* $b`#乘法需要添加一个转义字符
echo "a * b = $num"
num=`expr $a / $b`
echo "a / b = $num"
num=`expr $a % $b`
echo "a % b = $num"
if [ $a == $b ]
then
echo "a等于b"
fi
if [ $a != $b ]
then
echo "a不等于b"
fi

1.2.关系运算符
| 运算符 | 说明 | 举例1(a=10,b=20) |
|---|---|---|
| -eq(equal)(等同于==) | 相等,返回值为ture | [ $a -eq $b ] 返回false |
| -ne(not equal)(等同于!=) | 不等,返回值为ture | [ $a -ne $b ] 返回ture |
| -gt(greater than)(等同于>) | 大于,返回值为ture | [ $a -gt $b ] 返回false |
| -lt(litter than)(等同于<) | 小于,返回值为ture | [ $a -lt $b ] 返回ture |
| -ge(greater+equal)(等同于>=) | 大于等于,返回值为ture | [ $a -ge $b ] 返回false |
| -le(litter+equal)(等同于<=) | 小于等于,返回值为ture | [ $a -le $b ] 返回ture |
#!/bin/bash
a=10
b=20
if [ $a -eq $b ]
then
echo "a等于b"
else
echo "a不等于b"
fi
if [ $a -ne $b ]
then
echo "a不等于b"
else
echo "a等于b"
fi
if [ $a -gt $b ]
then
echo "a大于b"
else
echo "a不大于b"
fi#小于或等于
if [ $a -lt $b ]
echo "a不等于b"
else
echo "a等于b"
fi
if [ $a -ge $b ]#大于和等于是或的关系
then
echo "a大于等于b"
else
echo "a小于b"
fi
if [ $a -le $b ]
then
echo "a小于等于b"
else
echo "a大于b"
fi
if (($a==$b))
then
echo "a等于b"
else
echo "a不等于b"
fi
if (($a!=$b))
then
echo "a不等于b"
else
echo "a等于b"
fi
if (($a>$b))
then
echo "a大于b"
else
echo "a不大于b"
fi
if (($a<$b))
then
echo "a小于b"
else
echo "a不小于b"
fi
if (($a>=$b))
then
echo "a大于等于b"
else
echo "a小于b"
fi
if (($a<=$b))
then
echo "a小于等于b"
else
echo "a大于b"
fi

1.3.布尔(逻辑)运算符
| 运算符 | 说明 | 举例 |
|---|---|---|
| ! | 非运算,表达式为true 则返回 false,否则返回true | [ ! false ] 返回false |
| -o(or) | 或运算,有一个表达式为true则返回true | [ $a -lt 20 -o $b -gt 100 ] 返回true |
| -a(and) | 与运算,两个表达式都为true才返回true | [ $a -lt 20 -a $b -gt 100 ] 返回false |
#!/bin/bash
a=10
b=20
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a小于100且$b大于15 :true"
else
echo "$a小于100且$b大于15 :false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a小于100或$b大于100 :true"
else
echo "$a小于100或$b大于100 :false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a小于5或$b大于100 :true"
else
echo "$a小于5或$b大于100 :false "
fi

1.4.短路运算符
| 运算符 | 说明 | 举例(a=10,b=20) |
|---|---|---|
| && | 短路与,两边只要有一边的值为fasle , 虚拟机就不会再查看另外一边了 | [[ $a -lt 100 && $b -lt 100 ]] 返回ture |
| ll | 短路或,两边只要有一边的值为true, 虚拟机就不会再查看另外一边 | [[ $a -gt 100 ll $b -gt 100 ]] 返回false |
#!/bin/bash
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "$a小于100且$b大于100 :true"
else
echo "$a小于100且$b大于100 :false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "$a小于100或$b大于100 :true"
else
echo "$a小于100或$b大于100 :false"
fi
if [[ $a -lt 100 && $b -gt 10 ]]
then
echo "$a小于100且$b大于10 :true"
else
echo "$a小于100且$b大于10 :false"
fi
if [[ $a -lt 0 || $b -gt 100 ]]
then
echo "$a小于0或$b大于100 :true"
else
echo "$a小于0或$b大于100 :false"
fi

1.5.字符串运算符
| 运算符 | 说明 | 举例(a=abc,b=efg) |
|---|---|---|
| = | 检测两个字符串是否相等,相等返回true | [ $a = $b ] 返回false |
| != | 检测两个字符串是否相等,不等返回true | [ $a != $b ] 返回ture |
| -z(zero) | 检测字符串长度是否为0,为0返回true | [ -z $a ] 返回false |
| -n | 检测字符串长度是否为0,不为0返回true | [ -n “$a” ] 返回ture |
| $ | 检测字符串是否为空,不为空返回true | [ $a ] 返回ture |
#!/bin/bash
a='abc'
b="def"
if [ $a = $b ]
then
echo "a等于b"
else
echo "a不等于b"
fi
if [ $a != $b ]
then
echo "a不等于b"
else
echo "a等于b"
fi
if [ -z $a ]
then
echo "a长度为0"
else
echo "a长度不为0"
fi
if [ -n $a ]
then
echo "a长度不为0"
else
echo "a长度为0"
fi
if [ $a ]
then
echo "a不为空字符"
else
echo "a为空字符"
fi

1.6.文件测试运算符
| 运算符 | 说明 | 举例(file=“/root/test.sh”) |
|---|---|---|
| -r(read) | 判断文件(user权限)是否可读 | [ -r $file ] |
| -w(write) | 判断文件(user权限)是否可写 | [ -w $file ] |
| -x(execute) | 判断文件(user权限)是否可执行 | [ -x $file ] |
| -f(file) | 判断是否为文件 | [ -f $file ] |
| -d(directory) | 判断是否为目录 | [ -d $file ] |
| -s(substance物质,我猜的) | 判断文件是否为空 | [ -s $file ] |
| -e(execute) | 判断文件是否存在 | [ -e $file ] |
#!/bin/bash
file="/root/test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -r $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件为目录"
else
echo "文件不为目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi

扩——``,$()
- 可以把一个命令的标准输出插在命令行中的任何位置,也就是说写在``和$()中的字符会被当作命令去处理。
- 功能上``=$()
- 支持+ -*/%运算(bash只支持整数运算)。
- ``会自动识别并转义为特殊字符,但是$()需要手动添加转义字符()才可以。
扩——()、[]、{}、(())、[[]]等各种括号的使用
1、小括号()
1.1 单小括号()
- 命令组
- 括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。
- 括号中多个命令之间用分号隔开,最后⼀个命令可以没有分号,各命令和括号之间不必有空格。
- 命令替换
- 自动识别编译命令,类似于cmd,shell扫描一遍命令行,发现了$ (cmd)结构,便将$ (cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。
- 有些shell不支持,如tcsh。
- 初始化数组
- 数组的命名,如:array=(a b c d)。
1.2 双小括号(())
- 算数运算(整数)
- 这种算数计算是整数型的计算,不支持浮点型。
- ((exp))结构扩展并计算⼀个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者是"假",而⼀个非零值的表达式所返回的退出状态码将为0,或者是"true"。
- 若是逻辑判断,表达式exp为真则为1,假则为0。
- 只要括号中的运算符、表达式符合C语言运算规则,都可用在$ ((exp))中,甚至是三目(条件)运算符。
- 作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。
- 如:echo $ ((16#5f)) 结果为95 (16进位转十进制)
- 作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。
- 单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $ a 重定义为6。
- 常用于算术运算比较,双括号中的变量可以不使用$ 符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则。
- 比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in seq 0 4或者for i in {0…4}。再如可以直接使用if
(($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。
- 比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in seq 0 4或者for i in {0…4}。再如可以直接使用if
for((i=1;i<=5;i++));do echo -n $i;done
#-n 可以让结果成行输出12345,否则一行只输出一个结果
for i in $(seq 1 5);do echo -n $i;done
for i in `seq 1 5`;do echo -n $i;done
for((i=1;i<5;i++));do
> if(($i<4))
> then
> echo $i
> fi;done
for((i=1;i<5;i++)); do
> if [ $i -lt 4 ]
> then
> echo $i
> fi;done
2、中括号[]
2.1 单中括号[]
- 使用if/test命令时要接[]。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回⼀个退出状态码。
- test和[]中的比较运算符只有==和!=,两者都是用于字符串比较的,整数比较只能使用-eq,-gt这种形式。且二者都不支持大于号小于号。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。
- 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。
- 用来引用数组中元素的编号,array[n]。
2.2 双中括号[[]]
- [[是 bash 程序语言的关键字,并不是一个命令。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生算数运算和命令替换。
- 支持字符串的模式匹配,字符串比较时可以把右边的作为一个模式(字符串加命令),而不仅仅是⼀个字符串,比如[[ hello == hello? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。
- 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。
- 比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。
- 比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1 ] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
- bash把双中括号中的表达式看作一个单独的整体,并返回一个退出状态码。
[ 2 -lt 3 ]#[]之间只能识别==和!=,所以小于需要用-lt
[ 2\<3 ]#想使用<需要用到转义,转义的左右两端不能有空格否则会报错。
[[ 2 < 3 ]]#[[]]可以识别<等操作符
[[ 2 -lt 3 ]]
[[ 2\<3 ]]#使用转义字符和-lt也是可以的
3、大括号{}
- 拓展。对花括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。
- 对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。
- 对大括号中以点点(…)分割的顺序文件列表起拓展作用,如:touch {a…d}.txt 结果为a.txt b.txt c.txt d.txt。
- 代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,花括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后⼀个也必须有分号。{}的第⼀个命令和左括号之间必须要有⼀个空格。
扩——逻辑运算,算数运算,短路运算
- 短路运算类似逻辑运算,不过短路运算只要有一边的值为fasle /ture, 计算机就不会再查看另外的。
- 短路与,检测fasle;
- 短路或,检测ture。
- 逻辑运算的结果只有0和1两个,算数运算则是将值换算为二进制,对0/1进行按位计算,得到的结果换算1为十进制输出,所以算数运算的结果不局限于0/1。
二.echo打印数据
- 用于字符串的输出
##显示普通字符串
echo "Hello world"
##显示转义字符
echo "\"Hello world\""
##显示变量
name="zhangsan"
echo "$name Hello world"
##显示换行
echo -e "OK! \n"
echo "Hello world"
##显示不换行
echo -e "OK! \c"
echo "Hello world"
##显示结果定向至文件
echo "Hello world" > myfi1e
##原样输出字符串
echo '$name\"'
##显示命令执行结果
echo `ate`
三.test命令
- Shell中的test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
- 可以看作if语句的前缀语句。
- 数字
| 参数 | 说明 |
|---|---|
| -eq | 等于则为真 |
| -ne | 不等于则为真 |
| -gt | 大于则为真 |
| -ge | 大于等于则为真 |
| -lt | 小于则为真 |
| -le | 小于等于则为真 |
- 字符串
| 参数 | 说明 |
|---|---|
| = | 等于则为真 |
| != | 不等于则为真 |
| -z 字符串 | 字符串长度为零则为真 |
| -n 字符串 | 字符串长度不为零则为真 |
- 文件测试
| 参数 | 说明 |
|---|---|
| -e 文件名 | 如果文件存在则为真 |
| -r 文件名 | 如果文件存在且可读则为真 |
| -w 文件名 | 如果文件存在且可写则为真 |
| -x 文件名 | 如果文件存在且可执行则为真 |
| -s 文件名 | 如果文件存在且不为空则为真 |
| -d 文件名 | 如果文件存在且为目录则为真 |
| -f 文件名 | 如果文件存在且为普通文件则为真 |
| -c(char) 文件名 | 如果文件存在且为字符型特殊文件则为真 |
| -b(block) 文件名 | 如果文件存在且为块特殊文件为真 |
#比较
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi

四.Shell流程控制
4.1. if
- 语法
if condition1
then
command1
elif condition2
then
command2
else
comman dN
fi
- 举例
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b "
elif [ $a -lt $b ]
then
echo "a 小于 b "
else
echo "没有符合的条件"
fi

4.2.case
- Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
- 语法
case 值 in
模式1)
command1
command2
...
comman dN
;;
模式2)
command1
command2
...
comman dN
;;
esac
- 举例
#!/bin/bash
echo '你需要点什么:'
read num#类似于scanf
case $num in
汉堡)echo '你选择了汉堡';;
薯条)echo '你选择了薯条';;
可乐)echo '你选择了可乐';;
鸡翅)echo '你选择了鸡翅';;
*)echo '你选择了其他';;
esac#就是把case反过来

4.3. for
-
当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。
-
命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。
-
in列表是可选的,如果不用它,for循环使用命令行的位置参数。
-
语法
for 变量名 in 值列表(item1 item2 ... itemN)
do
command1
command2
commandN
done
for ((变量=初始值;变量结束条件;变量中间变化步骤))
do
command1
command2
commandN
done
- 举例
#!/bin/bash
for a in 1 2 3 4 5
do
echo "a的值为:$a"
done
for ((i=1;i<6;i++))
do
echo "i的值为:$i"
done
for str in 'This is a string'
do
echo $str
done
for str in 'This is a string',"thank you",'hello world'
#字符之间可以用逗号隔开,只要逗号之间没有空格,就会默认为一行输出,有空格则会另起一行输出。
do
echo $str
done

4.4. while
- while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。
- 语法
while condition
do
command
done
- 举例
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
#Bash let命令,它用于执行一个或多个表达式,变量计算中不需要加上$来表示变量
#无限循环
while true
do
command
done
4.5. break
- break命令允许跳出所有循环(终止执行后面的所有循环)。
- 举例
#!/bin/bash
while :
do
echo -n '请输入1到5之间的数字:'#-n可以使输入数字的时候不换行
read num
case $num in
1|2|3|4|5) echo "您输入的数字为: $num";;
*) echo "违规,出局"
break;;#直接跳出循环整体
esac
done

4.6. continue
- continue命令不会跳出所有循环,仅仅跳出当前循环。

- 举例
#!/bin/bash
while :
do
echo -n '请输入1到5之间的数字:' #-n可以使输入数字的时候不换行
read num
case $num in
1|2|3|4|5) echo "您输入的数字为: $num";;
*) echo "违规,继续"
continue #这里加上continue后就不会再输出游戏结束的语句了
#break和continue都要放在;;之内
echo "游戏结束";;
esac
done

五.Shell函数
- linux shell可以用户定义函数,然后在shell脚本中可以随便调用。
- 可以带function fun()定义,也可以直接fun()定义,不带任何参数。
- 参数返回,可以显示加: return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)。
- 其作用主要为实现代码的复用。
#! /bin/bash
##第一个函数------------
demoFun(){
echo "这是我的第一个 shell 函数! "
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
##函数返回值------------
funwithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字:“
read aNum
echo "输入第二个数字:"
read anotherNum
echo "两个数字分别为$aNum和 $anotherNum ! "
return $(($aNum+$anotherNum))
funwithReturn
#函数返回值在调用该函数后通过$?来获得。
echo "输入的两个数字之和为$? ! "
##函数参数------------
funwithParam(){
echo "第一个参数为$1 !"
echo "第二个参数为$2 !"
echo "第十个参数为$10 !"
echo "参数总数有$#个 !"
echo "作为一个字符串输出所有参数$* !"
}
funwithParam 1 2 3 4 5 6 7 8 9
