语句"/>
Shell之条件语句
条件语句
- 测试
- 比较整数数值
- 字符串比较
- 常用的测试操作符
- 逻辑测试(短路运算)
- 双中括号
- (){}
- if语句的结构
- 分支结构
- case
- echo
测试
test 测试文件的表达式 是否成立
Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时表示成功,否则(非0值)表示失败或异常。
test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为0表示条件成立)。
格式1: test 条件表达式
格式2: [ 条件表达式 ]
注意[]空格,否则会失败
测试 是否成功使用 $? 返回值
[ 操作符 文件或目录 ]
help test
操作符
操作符 | 含义 |
---|---|
-d | 测试是否为目录(Directory) |
-e | 测试目录或文件是否存在(Exist) |
-a | 测试目录或文件是否存在(Exist) |
-f | 测试是否为文件(File) |
-r | 测试当前用户是否有权限读取(Read) |
-w | 测试当前用户是否有权限写入(Write) |
-x | 测试当前用户是否有权限执行(eXcute) |
-L | 测试是否为软连接文件 |
属性测试补充
属性 | 含义 |
---|---|
-s | FILE #是否存在且非空 |
-t | fd #fd 文件描述符是否在某终端已经打开 |
-N | FILE #文件自从上一次被读取之后是否被修改过 |
-O | FILE #当前有效用户是否为文件属主 |
-G | FILE #当前有效用户是否为文件属组 |
条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成
测试过程,实现评估布尔声明,以便用在条件性环境下进行执行
若真,则状态码变量 $? 返回0
若假,则状态码变量 $? 返回1
条件测试命令
比较整数数值
[ 整数1 操作符 整数2 ] 公式
- -eq:第一个数等于(Equal)第二个数
- -ne:第一个数不等于(Not Equal)第二个数
- -gt:第一个数大于(Greater Than)第二个数
- -lt:第一个数小于(Lesser Than)第二个数
- -le:第一个数小于或等于(Lesser or Equal)第二个数
- -ge:第一个数大于或等于(Greater or Equal)第二个数
实例:
[root@test1 ~]# a=2
[root@test1 ~]# b=3
[root@test1 ~] [ $a -eq $b ]
[root@test1 ~]# echo $?
1
[root@test1 ~]# [ 2 -le 3 ]
[root@test1 ~]# echo $?
0
字符串比较
常用的测试操作符
- =:字符串内容相同
- !=:字符串内容不同,! 号表示相反的意思
- -z:字符串内容为空
- -n: 字符是否存在
格式
[ 字符串1 = 字符串2 ] 是否相同[ 字符串1 != 字符串2 ] 是否不相同[ -z 字符串 ] 是否为空[ -n 字符串 ] 字符是否存在
实例:
[root@localhost ~]# str1=wang
[root@localhost ~]# str2=zhou
[root@localhost ~]# [ $str1 = $str2 ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ $USER = root ]&& echo true
true
[root@localhost ~]# [ $USER != root ]&& echo true
[root@localhost ~]# read -p "yes/no:" ack
yes/no:yes
[root@localhost ~]# echo $ack
yes
[root@localhost ~]# [ -z $ack ] && echo true
[root@localhost ~]# read -p "是否覆盖当前文件 (yes/no)" ACK
是否覆盖当前文件 (yes/no)yes
[root@localhost ~]# [ $ACK = "yes" ] && echo "覆盖"
覆盖
[root@localhost ~]# read -p "是否覆盖当前文件 (yes/no)" ACK
是否覆盖当前文件 (yes/no)yes
[root@localhost ~]# [ $ACK = "no" ] && echo "不覆盖"
逻辑测试(短路运算)
格式
格式1:[ 表达式1 ] 操作符 [ 表达式2 ] ...
格式2:命令1 操作符 命令2 ...
常见条件:
- -a或&&:逻辑与,“而且”的意思全真才为真
- -o或||:逻辑或,“或者”的意思一真即为真
- !:逻辑否
(1)短路与 &&
CMD1 短路与 CMD2 && 同时满足命令1 和命令2 的要求 才会返回正确
全真才为真 一假即为假
第一个CMD1结果为真 ,第二个CMD2必须要参与运算,才能得到最终的结果
第一个CMD1结果为假 ,总的结果必定为假,因此不需要执行CMD2
(2)短路或 ||
CMD1 短路或 CMD2
一真即为真
第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2
第一个CMD1结果为假 (0),第二个CMD2 必须要参与运算,才能得到最终的结果
实例:
[root@localhost ~]# uname -r
3.10.0-693.el7.x86_64
[root@localhost ~]# uname -r |awk -F. '{print $1}'
3
[root@localhost ~]# uname -r |awk -F. '{print $2}'
10
[root@localhost ~]# MAIN=$(uname -r |awk -F. '{print $2}')
[root@localhost ~]# SAIN=$(uname -r |awk -F. '{print $1}')
[root@localhost ~]# [ $SAIN -ge 3 ]&& [ $MAIN -ge 4 ]&& echo "yes"
yes
[root@localhost ~]# [ ! -d mmm ] && echo "yes"
yes
[root@localhost ~]# [ 4 -lt 5 ]&&echo true || echo false
true
[root@localhost ~]# [ 4 -gt 5 ]&&echo true || echo false
false
[root@localhost ~]# [ 4 -gt 5 ]&& echo true ||echo false
false|| 只有前面不成立时才会执行后面的操作
双中括号
[[ expression ]] 用法
== 左侧字符串是否和右侧的PATTERN相同注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配注意: 此表达式用于[[ ]]中;扩展的正则表达式
实例:
[root@localhost ~]# FILE=test.log
[root@localhost ~]# [[ "$FILE" == *.log ]]
[root@localhost ~]# echo $?
0
[root@localhost ~]# FILE=test.txt
[root@localhost ~]# [[ "$FILE" == *.log ]]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [[ "$FILE" != *.log ]]
[root@localhost ~]# echo $?
0
(){}
(CMD1;CMD2;…)和 {空格CMD1;CMD2;…; } 都可以将多个命令组合在一起,批量执行
实例:
[root@localhost ~]# ( cd /data;ls )
test.txt
[root@localhost ~]# pwd
/root
[root@localhost ~]# { cd /data;ls; }
test.txt
[root@localhost data]# pwd
/data#()会开启子shell
[root@localhost ~]# echo $BASHPID
3839
[root@localhost ~]# ( echo $BASHPID;sleep 100)
4016
^C
[root@localhost ~]# pstree -p
systemd(1)─┬─ModemManager(719)─┬─{ModemManager}(757)│ └─{ModemManager}(792)├─NetworkManager(868)─┬─{NetworkManager}(883)│ └─{NetworkManager}(885)├─VGAuthService(726)├─abrt-watch-log(723)├─abrtd(721)├─accounts-daemon(734)─┬─{accounts-daemon}(755)│ └─{accounts-daemon}(791)├─alsactl(720)├─anacron(3950)
.......................................#{ } 不会开启子shell
[root@localhost ~]# echo $BASHPID
3839
[root@localhost ~]# { echo $BASHPID; }
3839[root@localhost ~]# name=lc
[root@localhost ~]# ( name=mcl;echo $name );echo $name
mcl
lc
[root@localhost ~]# name=lc
[root@localhost ~]# { name=mcl;echo $name; };echo $name
mcl
mcl
if语句的结构
分支结构
单分支
if 判断条件;then 条件为真的分支代码fi
双分支
if 判断条件; then条件为真的分支代码else条件为假的分支代码fi
多分支
if 判断条件1
then条件1为真的分支代码elif 判断条件2
then条件2为真的分支代码elif 判断条件3;then条件3为真的分支代码...
else以上条件都为假的分支代码fi
实例:
#单分支###########判断是否为超级管理员#######################
#!/bin/bash
if [ "$USER" != "root" ]
thenecho "非管理员用户无权限操作"
else
echo "是管理员用户"
fi###########判断是主机连通性#######################
#!/bin/bash
ping -c 3 192.168.91.1
if[ $? = 0 ]
thenecho "与真机网络通顺"exit 1
fiecho "与真机网络不通"#######################多分支#######################
#!/bin/bash
read -p "请输入你的考试分数:" gradeif [ $grade -ge 85 ]&& [ $grade -le 100 ]
then
echo "你的成绩为$grade"
echo "你的成绩为优秀"elif [ $grade -ge 70 ]&&[ $grade -le 84 ]
then
echo "你的成绩为$grade"
echo "你的成绩为良好"
elif
[ $grade -ge 60 ]&&[ $grade -le 69 ]
then
echo "你的成绩为$grade"
echo "你的成绩为合格"
else
echo "你的成绩为$grade"
echo "你的成绩不合格"
fi#!/bin/bash
h=`date +%H`
if [ $h -ge 6 -a $h -le 10 ];then
echo "早上好"
elif [ $h -ge 11 -a $h -le 13 ];then
echo "中午好"
elif [ $h -ge 14 -a $h -le 18 ];then
echo "下午好"
else
echo "晚上好"
fi
case
格式
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esaccase 变量引用 in
PAT1)分支1;;
PAT2)分支2;;
...
*)默认分支;;case支持glob风格的通配符:
* 任意长度任意字符
? 任意单个字符
[0-9] 指定范围内的任意单个字符
| 或者,如: a|b
echo
实例:
echo -n 表示不换行输出
echo -e 表示输出转义符
常用的转义符
选项 | 作用 |
---|---|
选项 | |
---- | ---- |
\r | 光标移至行首,并且不换行 |
\s | 当前shell的名称,如bash |
\t | 插入Tab键,制表符 |
\n | 输出换行 |
\f | 换行,但光标仍停留在原处 |
\ | 表示插入"\"本身转义 |
\b | 表示退格 不显示前一个字符 |
\c | 抑制更多的输出或不换行 |
实例:
[root@localhost ~]# echo -e "12345\b678" ##退格删除前面的字符
1234678
[root@localhost ~]# echo -e "12345\b\b678"
123678
[root@localhost ~]# echo -e "12345\b\b\b678"
12678
[root@localhost ~]# echo -e "12345\b\b\b\b678"
16785
###注意退格键和末尾的字符相关,超过末尾的字符数量 会出bug 了解即可[root@localhost ~]# echo -e "12345678\c"
12345678[root@localhost ~]# echo -e "1234\c5678"
1234[root@localhost ~]# ###\c 注意 使用在数字中间会把后面内容删除
date
date查看当前系统时间
-d 你描述的日期,显示指定字符串所描述的时间,而非当前时间
%F 完整日期格式,等价于 %Y-%m-%d
% T 时间(24小时制)(hh:mm:ss)
实例:
[root@localhost ~]# date -d '-1 day' +%F
2023-02-04
[root@localhost ~]# date +%F
2023-02-05
[root@localhost ~]# date -d '1 day ' +%F-%T
2023-02-06-10:08:17
[root@localhost ~]# date -d "-3 day" #前三天
2023年 02月 02日 星期四 10:08:32 CST
[root@localhost ~]# date -d "+3 day" #后三天
2023年 02月 08日 星期三 10:08:40 CST
[root@localhost ~]# date -d '1 day ' +%F' '%T
2023-02-06 10:08:49
[root@localhost ~]# cal 2021 #查看日历2021 一月 二月 三月
日 一 二 三 四 五 六 日 一 二 三 四 五 六 日 一 二 三 四 五 六1 2 1 2 3 4 5 6 1 2 3 4 5 63 4 5 6 7 8 9 7 8 9 10 11 12 13 7 8 9 10 11 12 13
10 11 12 13 14 15 16 14 15 16 17 18 19 20 14 15 16 17 18 19 20
17 18 19 20 21 22 23 21 22 23 24 25 26 27 21 22 23 24 25 26 27
24 25 26 27 28 29 30 28 28 29 30 31
31四月 五月 六月
日 一 二 三 四 五 六 日 一 二 三 四 五 六 日 一 二 三 四 五 六1 2 3 1 1 2 3 4 54 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 3030 31七月 八月 九月
日 一 二 三 四 五 六 日 一 二 三 四 五 六 日 一 二 三 四 五 六1 2 3 1 2 3 4 5 6 7 1 2 3 44 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11
11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18
18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25
25 26 27 28 29 30 31 29 30 31 26 27 28 29 30十月 十一月 十二月
日 一 二 三 四 五 六 日 一 二 三 四 五 六 日 一 二 三 四 五 六1 2 1 2 3 4 5 6 1 2 3 43 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
31[root@localhost ~]# cal 9 1752九月 1752
日 一 二 三 四 五 六1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30***
crontab 里 不能有 % 号
30 2 * * * /bin/cp -a /etc/ /data/etc`date +\%F_\%T`
30 2 * * * /bin/cp -a /etc/ /data/etc`date +‘%F_%T’`
更多推荐
Shell之条件语句
发布评论