文章目录
条件测试操作
Shell 环境通过命令执行后的返回状态值($?
)来判断是否执行成功。当返回值为 0(真,true)时表示成功,返回值为非 0 值(假,false)时表示失败或异常。
test
命令可以对特定条件进行测试,并根据返回值来判断条件是否成立($?
返回值为 0 表示条件成立)。
格式:
-
格式一:
test 条件表达式
-
格式二(简写):
[ 条件表达式 ]
注意:方括号[ 和 ]与条件表达式之间需要至少一个空格进行分隔。
文件测试
格式:
[ 操作符 文件或目录 ]
常用操作符:
- -e:测试目录或文件是否存在 (Exist)
- -d:测试是否为目录 (Directory)
- -f:测试是否为文件 (File)
- -r:测试当前用户是否有权限读取 (Read)
- -w:测试当前用户是否有权限写入(Write)
- -x:测试是否设置有可执行(Excute)权限。
- -L:测试是否为符号链接
整数值比较
格式:
[ 整数变量1 操作符 整数变量2 ]
常用操作符:
- -eq:等于
==
(等于equal) - -ne:不等于
!=
(not equal) - -gt:大于
\>
(大于greater) - -lt:小于
\<
(小于les) - -le:小于等于
<=
- -ge:大于等于
>=
test 1 -eq 1
echo $?
字符串比较
格式 1:
[ 字符串1 = 字符串2 ]
或[ 字符串1 == 字符串2 ]
[ 字符串1 != 字符串2 ]
[root@localhost ~]# test yht == dxl
[root@localhost ~]# echo $?
1
[root@localhost ~]# test yht == yht
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ dxl == wujian ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ wujian == wujian ]
[root@localhost ~]# echo $?
0
格式 2:
[ -z "字符串" ]
:检查字符串是否为空(Zero),对于未定义或赋予空值的变量将视为空串。[ -n "字符串" ]
:检查是否有字符串存在。(使用引号,防止扰乱空格)
逻辑测试
格式 1:
[ 表达式1 ] 操作符 [ 表达式2 ]
格式 2:
命令1 操作符 命令2
常用操作符:
- -a 或
&&
:逻辑与,表示“而且”,前后条件需都成立。 - -o 或
||
:逻辑或,表示“或者”,只需前后条件中一个成立。 !
:逻辑否。
a=5
[ $a -ne 1 ] && [ $a != 2 ]
# 等同于
[ $a -ne 1 -a $a != 2 ] # 不用两个中括号
注意:
&&
、||
操作符能够正常存在于[[ ]]
条件判断结构中,但如果出现在[ ]
结构中,会报错。
单双中括号
- 单中括号
[]
- 功能:用于测试表达式的真假,是一种命令,将测试表达式视为参数。
- 使用要求:
- 测试表达式中的各个部分需要用空格分隔。
- 变量通常需要用双引号引起来,以防止空值或特殊字符引发错误。
- 注意事项:
- 如
[ $var -eq 1 ]
可能会因为$var
为空而导致语法错误,而[ "$var" -eq 1 ]
是正确的写法。 - 单中括号的表达式有限,不支持复杂的模式匹配或正则表达式。
- 如
- 双中括号
[[ ]]
- 功能:也用于测试表达式的真假,但支持更复杂的表达式测试。
- 额外特性:
- 支持模式匹配、字符串操作、正则表达式等高级特性。
- 自动识别和处理变量中的空格,无需显式引用变量。
- 使用建议:由于双中括号功能更强大,建议在编写脚本时优先使用双中括号
[[ ]]
。
示例:
[[ $a != 1 && $a != 2 ]]
[[ 2 -lt 3 ]] && echo true || echo false
[[ 2 -ge 3 ]] && echo true || echo false
综合示例:检测指定IP地址或主机是否在线
vim pinghost.sh
#!/bin/bash
ping -c 3 -i 0.5 -W 2 $1 &> /dev/null && echo "$1 online" || echo "$1 off"
[root@localhost ~]# sh ip.sh 192.168.233.21
192.168.233.21 online
# 解释:
-c 3:发送3个ICMP请求包(Ping的次数)。
-i 0.5:每个Ping请求之间间隔0.5秒。
-W 2:等待每个Ping响应的超时时间为2秒。(-w:多少秒后停止 ping 命令操作)
$1:脚本执行时传入的第一个参数,即目标IP地址或主机名。
&> /dev/null:将ping命令的输出重定向到/dev/null,即忽略输出结果,只关心命令的返回值。
&& echo "$1 online":
&& 是逻辑与运算符,表示如果前面的ping命令执行成功(即返回值为0),则执行echo "$1 online",表示目标主机在线。
|| echo "$1 off":
|| 是逻辑或运算符,表示如果前面的ping命令执行失败(即返回值非0),则执行echo "$1 off",表示目标主机不在线。
if 语句
单分支 if
语句
格式:
if 条件测试操作
then
命令序列
fi
示例:
if [ 3 -gt 2 ];
then
echo "ok";
fi
[ 3 -gt 2 ] && echo "ok"
双分支 if
语句
格式:
if 条件测试操作
then
命令序列 1
else
命令序列 2
fi
示例:
vim pinghost1.sh
#!/bin/bash
ping -c 3 -i 0.5 -W 2 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo "$1 online"
else
echo "$1 off"
fi
多分支 if
语句
格式:
if 条件测试操作 1
then
命令序列 1
elif 条件测试操作 2
then
命令序列 2
[else]
[命令序列 3]
fi
示例:
vim score.sh
#!/bin/bash
read -p "请输入您的分数(0-100): " score
if [ $score -ge 85 ] && [ $score -le 100 ]
then
echo "$score 分,优秀!"
elif [ $score -ge 70 ] && [ $score -le 84 ]
then
echo "$score 分,合格!"
else
echo "$score 分,不合格!"
fi
双小括号
$(())
语法说明
在 Bash 中,$(( ))
语法用于进行算术运算。
示例
判断变量 num
是否为偶数。假设变量 num
已经通过 read
命令定义为一个整数:
read -p "请输入一个数字: " num
if [ $(($num % 2)) -eq 0 ]; then
echo "$num 是偶数"
else
echo "$num 是奇数"
fi
解析
$(( ))
语法:- Bash 中的算术运算符,可以执行加、减、乘、除、取模等操作。
- 当其中包含变量时,Bash 会自动解析变量的值并进行运算。
- 余数计算:
- 此例中,表达式
$(($num % 2))
计算num
除以 2 的余数。 - 如果余数为 0,表示
num
是一个偶数。
- 此例中,表达式
- 使用场景:
$(( ))
适用于需要进行算术运算的情况,常用于判断、循环等场景。 - 自动解析:Bash 在执行
$(($num % 2))
时,会自动将变量num
的值替换到表达式中,并进行计算。
case 语句
格式:
case 变量值 in
模式 1)
命令序列 1
;;
模式 2)
命令序列 2
;;
……
* )
默认命令序列
esac
使用 case
分支语句的特点:
case
行尾必须为单词in
,每一模式必须以右括号)
结束。- 双分号
;;
表示命令序列的结束。 - 模式字符串中,可以用方括号表示一个连续的范围,如
[0-9]
;还可以用竖杠符号|
表示或,如A|B
。 - 最后的
*)
表示默认模式,其中的*
相当于通配符。
示例:
vim score1.sh
#!/bin/bash
read -p "请输入您的分数(0-100): " score
[[ $score -ge 80 && $score -le 100 ]] && a="great"
[[ $score -ge 60 && $score -lt 80 ]] && a="standard"
[[ $score -ge 0 && $score -lt 60 ]] && a="false"
case $score in
great)
echo "$score 分,优秀!"
;;
standard)
echo "$score 分,合格!"
;;
false)
echo "$score 分,不合格!"
;;
*)
echo "输入有误!"
esac
vim /etc/init.d/firewalld.sh
case $1 in
start)
echo -n "正在启动 firewalld 服务 ... "
systemctl start firewalld.service
echo "OK"
;;
stop)
echo -n "正在停止 firewalld 服务 ... "
pkill "firewalld" &> /dev/null
echo "OK"
;;
restart)
$0 stop
$0 start
;;
status)
if pgrep "firewalld" &>/dev/null ; then
echo "firewalld 服务已经启动."
else
echo "firewalld 服务已经停止."
fi
;;
* )
echo "用法: $0 {start|stop|status|restart}"
esac