Linux7.6—Shell编程
第三章:Shell高级进阶
文章目录
- Linux7.6—Shell编程
- 一.Shell运算符
-
- 1.1.算数运算符
- 1.2.关系运算符
- 1.3.布尔(逻辑)运算符
- 1.4.短路运算符
- 1.5.字符串运算符
- 1.6.文件测试运算符
- 扩——``,$()
- 扩——()、[]、{}、(())、[[]]等各种括号的使用
-
- 扩——逻辑运算,算数运算,短路运算
- 二.echo打印数据
- 三.test命令
- 四.Shell流程控制
-
- 4.1. if
- 4.2.case
- 4.3. for
- 4.4. while
- 4.5. break
- 4.6. continue
- 五.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