shell脚本编程(小白基础学习2)

shell脚本语言的运算

1.条件测试命令

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便在条件性环境下进行执行。

*   若真,则状态码变量$?返回0
*   若假,则状态码变量$?返回1

 扩展: [ ] 与 [[ ]] 的区别

`区别1:
[ ]是符合POSIX标准的测试语句,兼容性强,几乎可以运行在所有的Shell解释器中
[[ ]]仅可运行在特定的几个Shell解释器中(如Bash)

`区别2:
> < 可以在[[ ]]中使用ASCII码顺序进行排序,而[]不支持

`区别3:
在[ ]中使用-a 和 -o 表示逻辑与和逻辑或,[[ ]]使用&& 和 || 表示,[[ ]]不支持-a

`区别4:
在[ ]中==是字符匹配,在[[ ]]中==是模式匹配

`区别5:
[ ]不支持正则匹配,[[ ]]支持用=~进行正则匹配

`区别6:
[ ]仅在部分Shell中支持用()进行分组,[[ ]]均支持

`区别7:
在[ ]中如果变量没有定义,那么需要用双引号引起来,在[[ ]]中不需要

1.1 条件测试命令及其语法

语法1:test <测试表达式> 说明:test命令和<测试表达式>之间至少有一个空格

##### 4.4.1 条件测试命令及其语法

> 语法1:test <测试表达式> 说明:test命令和<测试表达式>之间至少有一个空格

语法2:[<测试表达式>] 说明:该方法和test命令的用法一样,[]的两边和内容之间至少有一个空格

root@localhost ~]# [ 1 -gt 3 ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 1 -lt 3 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# 

语法3:[[ <测试表达式> ]] 说明:比test和\[\]更新的语法格式。[[]]的边界和内容之间至少有一个空格。[[]]中可以使用通配符等进行模式匹配

[root@localhost ~]# [[ 1 > 3 ]]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [[ 1 < 3 ]]
[root@localhost ~]# echo $?
0
[root@localhost ~]# 

语法4:((<测试表达式>)) 说明:一般用于if语句里,双小括号两端不需要有空格,测试对象只能是整数

[root@localhost ~]# ((1<2))
[root@localhost ~]# echo $?
0
[root@localhost ~]# ((1>2))
[root@localhost ~]# echo $?
1
[root@localhost ~]# 

1.2 变量测试

语法规则:-v VAR 变量var是否被定义

示例:判断NAME变量是否被定义

[root@localhost ~]# [[ -v NAME ]]
[root@localhost ~]# echo $?
1
[root@localhost ~]# NAME=1
[root@localhost ~]# [[ -v NAME ]]
[root@localhost ~]# 
[root@localhost ~]# echo $?
0
[root@localhost ~]# 

语法规则: -R VAR 变量VAR是否被引用

> 示例:判断NAME变量是否被引用

[root@localhost ~]# NAME=10
[root@localhost ~]# test -v NAME
[root@localhost ~]# echo $?
0
[root@localhost ~]# test -R NAME
[root@localhost ~]# echo $?
1
[root@localhost ~]# 

1.3 文件测试表达式

常用的文件测试操作符说明
-a/-e 文件文件是否存在
-d 文件文件存在且为目录则为真,即测试表达式成立
-f 文件文件存在且为普通文件则为真,即测试表达式成立
-r 文件文件存在且可读为真
-w 文件文件存在且可写为真
-x 文件文件存在且可执行则为真

测试文件

[root@localhost ~]# test -a test.txt
[root@localhost ~]# echo $?
1
[root@localhost ~]# test -d shell
[root@localhost ~]# echo $?
0
[root@localhost ~]# touch test.txt
[root@localhost ~]# test -w test.txt &&echo "true"
true
[root@localhost ~]# test -r test.txt &&echo "true"
true
[root@localhost ~]# test -x test.txt &&echo "true"
[root@localhost ~]# 

1.4 字符串测试表达式

常用字符串测试操作符说明
-z ”字符串“若字符串的长度为0,则为真,z可以理解为zero

测试字符串

[root@localhost ~]# var_test='mike'
[root@localhost ~]# echo $var_test 
mike
[root@localhost ~]# [[ -n var_test ]] && echo "True"
True

1.5 整数测试表达式

在[ ] 或 test中使用的比较符号在(( )) 或 [[  ]]中使用的比较符号(不用这个做数字比较)说明

-eq

\== 或 =相等
-ne

!=

不相等
-gt>大于
-ge>=大于等于
-lt<小于
-le<=小于等于

1.6 逻辑操作符

在[ ] 中使用的操作符在test, [[ ]] , (( ))中使用的逻辑操作符说明
-a&&and,与,两边都为真,则结果为真
-o||or,或,有真则真,同假则假
!!not,非,两端相反,则结果相反
[root@ansible-salve1 ~]# var_test=1
[root@ansible-salve1 ~]# var_t=2
[root@ansible-salve1 ~]# [ $var_test -lt 0 -a $var_t -gt 0 ]
[root@ansible-salve1 ~]# echo $?
1
[root@ansible-salve1 ~]# [ $var_test -lt 0 -o $var_t -gt 0 ]
[root@ansible-salve1 ~]# echo $?
0
[root@ansible-salve1 ~]# 

1.5 关于()与 { }

( )和 { }都可以将多个命令组合再一次,批量执行,{ } 里的内容需要与两侧用空格隔开并在命令结尾加上;

  ( )会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境

[root@ansible-salve1 ~]# name=mage;(echo $name;name=wang;echo $name);echo $name
mage
wang
mage

[root@ansible-salve1 ~]# (umask 444;umask);umask
0444
0022
[root@ansible-salve1 ~]# (umask 444;touch 1.txt);umask
0022
[root@ansible-salve1 ~]# ll 1.txt 
--w--w--w- 1 root root 0 11月 13 22:12 1.txt
[root@ansible-salve1 ~]# echo $BASHPID
1418
[root@ansible-salve1 ~]# (echo $BASHPID; sleep 3)
1501

{ } 不会开启子shell,在当前shell中运行,会影响当前shell环境

[root@ansible-salve1 ~]# name=mage;{ echo $name;name=wang;echo $name; };echo $name
mage
wang
wang
[root@ansible-salve1 ~]# { umask 444;touch 1.txt; };umask
0444
[root@ansible-salve1 ~]# umask
0444
[root@ansible-salve1 ~]# ll 1.txt 
--w--w--w- 1 root root 0 11月 13 22:23 1.txt
[root@ansible-salve1 ~]# echo $BASHPID
1418
[root@ansible-salve1 ~]# { echo $BASHPID; sleep 3; }
1418
[root@ansible-salve1 ~]#  

1.6 组合测试条件

1.6.1 第一种方式[ ]

[ EXPRESSION1  -a EXPRESSION2]  并且 ==> 条件1与条件2都为真,结果才为真
[ EXPRESSION1  -O EXPRESSION2]  或  ==> 条件1与条件2只要有一个为真,结果就为真
[ !EXPRESSION1 ]  取反

说明:-a 和 -o 需要使用测试命令执行,[[ ]] 不支持

[root@ansible-salve1 ~]# ll 1.txt 
--w--w--w- 1 root root 0 11月 13 22:23 1.txt
[root@ansible-salve1 ~]# FILE=/root/1.txt 
[root@ansible-salve1 ~]# [ -f $FILE -a -x $FILE ]
[root@ansible-salve1 ~]# echo $?
1
[root@ansible-salve1 ~]# chmod +x /root/1.txt 
[root@ansible-salve1 ~]# [ -f $FILE -a -x $FILE ]
[root@ansible-salve1 ~]# echo $?
0
[root@ansible-salve1 ~]# 

1.6.2 第二种方式[[ ]]

COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2

COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

! COMMAND #非,取反


# 结论:如果&& 和 || 混合使用,&&要在前,||放在后

案例:

[root@ansible-salve1 ~]# id hehao &> /dev/null  || useradd hehao  # 前面执行不成功,则执行后面的语句
[root@ansible-salve1 ~]# id hehao &> /dev/null  && echo "此账户已存在"
此账户已存在
[root@ansible-salve1 ~]# 

[root@ansible-salve1 ~]# IP=10.0.0.11;ping -c1 -w1 $IP &> /dev/null && echo $IP is up || echo $IP is down
10.0.0.11 is down
[root@ansible-salve1 ~]# IP=192.168.80.1;ping -c1 -w1 $IP &> /dev/null && echo $IP is up || echo $IP is down
192.168.80.1 is up
[root@ansible-salve1 ~]# 

示例:磁盘空间的判断

1.7 使用read命令命令来接受输入

 read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行**重定向**,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据

1.7.1 语法结构

read [option] [variables]

--options表示选项

--variables表示用来存储数据的变量,可以有一个,也可以有多个。

-- options和variables都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY 中。

1.7.2 选项:

Option说明
-a array把读取的数据赋值给数组array,从下标0开始
-p prompt显示提示信息,提示内容为prompt
 -t seconds设置超时时间,单位为秒。如果用户没能按时完成,返回一个非0的退出状态
-s静默模式,不会再屏幕上显示输入的字符。例如:输入密码

示例:使用read给多个变量赋值并输出

[root@localhost ~]# vim read.sh
[root@localhost ~]# ./read.sh
请输入你的姓名:yang
Hello, yang !
请输入你的年龄:20
Oh my god, you are so young!
[root@localhost ~]# ./read.sh
请输入你的姓名:yang
Hello, yang !
请输入你的年龄:40
I go you are old hight!
[root@localhost ~]# cat read.sh 
#!/bin/bash
read -p  "请输入你的姓名:" name
echo "Hello, $name !"
read -p  "请输入你的年龄:" age

[ $age -lt 30 ] && echo "Oh my god, you are so young!" || echo "I go you are old hight!"
[root@localhost ~]# 

2、流程控制

2.1 条件选择

2.1.1 选择执行if语句

if结构:

[root@localhost ~]# help if
if: if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
    根据条件执行命令。
    
    执行 "if 命令" 列表。如果退出状态为零,则执行 "then 命令" 列表。
    否则按顺序执行每个 "elif 命令" 列表,如果某一个的退出状态为零,则执行
    对应的 "then 命令" 列表,然后 if 命令完成。否则,执行 "else 命令"
    列表(如果有的话)。整个结构的退出状态是最后一个执行的命令的状态,
    或者如果没有一个条件的测试结果为真,则退出状态为零。
    
    退出状态:
    返回最后一个执行的命令的状态。
[root@localhost ~]# 

2.1.1.1 单分支

if [ 条件判断式 ];then
	命令
fi 

或者

if [ 条件判断式 ]
  then
   命令
fi

2.1.1.2 双分支

if [ 条件判断式 ]
  then
    命令
else
   命令
fi

1.1.1.3 多分支

if [ 条件判断式1 ]
 then
  命令
elif [ 条件判断式2 ]
 then 
  命令
...
...
else
 命令
fi

示例:依据BMI参数写出判断语句

[root@localhost ~]# vim info5.sh
[root@localhost ~]# chmod +x info5.sh
[root@localhost ~]# ./info5.sh
请输入身高(m为单位):175
请输入体重(Kg为单位):70
你太瘦了,请注意身体建康
[root@localhost ~]# cat info5.sh
#!/bin/bash
read -p "请输入身高(m为单位):" HIGH
if [[ ! "$HIGH" =~ ^[0-2].?[0-9]{,2}$ ]]
   then
           echo "请不要输入错误的身高";
           exit 1;
fi
read -p "请输入体重(Kg为单位):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]]
   then
           echo "请不要输入错误的体重";
           exit 1;
fi

BMI=`echo $WEIGHT/$HIGH^2|bc` 

if [ $BMI -le 18 ] ;then
        echo "你太瘦了,请注意身体建康"
elif [ $BMI -lt 24 ] ;then
        echo "身材很棒!"
else
        echo "你太胖了,注意节食,加强运动"
fi
[root@localhost ~]# 

说明:

*   多个if条件时,逐个条件进行判断,第一次遇见为“真”条件时,执行其分支,而后结束整个if语句
*   if语句可嵌套

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值