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`
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。 初始化数组
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= 1 ; i<= 5 ; i++ )) ; do echo -n $i ; done
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 ]
[ 2 \ < 3 ]
[ [ 2 < 3 ] ]
[ [ 2 -lt 3 ] ]
[ [ 2 \ < 3 ] ]
3、大括号{}
拓展。对花括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。
对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。 对大括号中以点点(…)分割的顺序文件列表起拓展作用,如:touch {a…d}.txt 结果为a.txt b.txt c.txt d.txt。 代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,花括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后⼀个也必须有分号。{}的第⼀个命令和左括号之间必须要有⼀个空格。
扩——逻辑运算,算数运算,短路运算
短路运算类似逻辑运算,不过短路运算只要有一边的值为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
case $num in
汉堡) echo '你选择了汉堡' ; ;
薯条) echo '你选择了薯条' ; ;
可乐) echo '你选择了可乐' ; ;
鸡翅) echo '你选择了鸡翅' ; ;
*) echo '你选择了其他' ; ;
esac
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
while true
do
command
done
4.5. break
break命令允许跳出所有循环(终止执行后面的所有循环)。 举例
#!/bin/bash
while :
do
echo -n '请输入1到5之间的数字:'
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之间的数字:'
read num
case $num in
1 | 2 | 3 | 4 | 5 ) echo "您输入的数字为: $num " ; ;
*) echo "违规,继续"
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