03-条件判断
为什么学条件判断
自动化任务处理的需求
- 在系统管理和运维工作中,经常需要批量处理任务。例如,你可能需要在服务器上检查一系列文件是否存在,如果存在就进行备份操作。通过Bash条件判断,可以编写脚本来自动完成这个过程。假设你有一个脚本,用于备份配置文件:
if [ ! -d /backup ];then echo "/backup备份目录不存在,帮您创建了!" mkdir -p /backup fi # 666 for file in /etc/*.conf; do if [ -e $file ]; then cp $file /backup/$(basename $file) fi done
- 这个脚本会遍历
/etc/
目录下所有以.conf
结尾的文件。对于每个文件,它会使用条件判断-e
来检查文件是否存在。如果文件存在,就将其复制到/backup/
目录下。这种自动化的任务处理可以大大提高工作效率,减少人工操作的错误。
- 在系统管理和运维工作中,经常需要批量处理任务。例如,你可能需要在服务器上检查一系列文件是否存在,如果存在就进行备份操作。通过Bash条件判断,可以编写脚本来自动完成这个过程。假设你有一个脚本,用于备份配置文件:
软件安装和配置的灵活性
- 当编写软件安装脚本时,Bash条件判断可以根据系统环境做出不同的决策。例如,不同的Linux发行版可能将软件安装在不同的目录下,或者需要不同的依赖包。通过条件判断,可以使安装脚本适应多种环境。
- 比如,以下是一个简单的软件安装脚本片段,用于判断系统是基于Debian(如Ubuntu)还是基于Red Hat(如CentOS)来安装软件:
if [ -f /etc/debian_version ]; then apt -y install software_name elif [ -f /etc/redhat-release ]; then yum -y install software_name else echo "Unsport system.." fi
- 这个脚本通过检查特定的系统版本文件(
/etc/debian_version
用于Debian系系统,/etc/redhat - release
用于Red Hat系系统)来决定使用apt
还是yum
命令安装软件。如果无法识别系统类型,会给出相应的提示信息。
错误处理和健壮性增强
- 在脚本执行过程中,可能会遇到各种错误情况,如文件不存在、权限不足等。使用Bash条件判断可以捕获这些错误并采取适当的措施。例如:
file_path="/tmp/file.txt" if [ -e $file_path ]; then if [ -r $file_path ]; then cat $file_path else echo "You don't have permission to read this file" fi else echo "File does not exist" fi
- 这个脚本首先检查文件是否存在(
-e
操作符),如果存在,再检查是否有读取权限(-r
操作符)。如果有读取权限,就显示文件内容;如果没有读取权限,会给出相应提示;如果文件不存在,也会给出提示。这样可以让脚本在遇到不同问题时能够合理地处理,增强了脚本的健壮性。
- 在脚本执行过程中,可能会遇到各种错误情况,如文件不存在、权限不足等。使用Bash条件判断可以捕获这些错误并采取适当的措施。例如:
实现复杂的逻辑和流程控制
- 对于复杂的系统管理任务或数据处理任务,需要根据多种条件来控制程序的流程。Bash条件判断可以帮助实现类似于其他高级编程语言中的复杂逻辑。例如,在一个日志分析脚本中,可能需要根据日志的级别和内容来采取不同的操作:
log_file="/var/log/syslog" while read line; do if echo $line | grep -q "ERROR"; then echo "Error found: $line" >> errors.log elif echo $line | grep -q "WARN"; then echo "Warning found: $line" >> warnings.log else continue fi done < $log_file
- 这个脚本逐行读取日志文件(
access.log
)。如果某行包含“ERROR”字样,就将该行内容通过邮件发送给管理员;如果包含“WARN”字样,就将该行内容追加到warnings.log
文件中;否则,跳过该行继续读取下一行。这种复杂的流程控制使得脚本能够根据不同的条件进行智能的处理。
- 对于复杂的系统管理任务或数据处理任务,需要根据多种条件来控制程序的流程。Bash条件判断可以帮助实现类似于其他高级编程语言中的复杂逻辑。例如,在一个日志分析脚本中,可能需要根据日志的级别和内容来采取不同的操作:
我们目前写的shell脚本都是按照顺序,自上而下的,依次读取命令,且执行。
但是如果你要控制程序的执行顺序,修改这个顺序,那就得对脚本进行逻辑控制。
那么就必须得进行条件判断了。
坑记录。
1.务必注意,语法,中括号,条件测试符号左右两边的空格,别漏了。
2.条件判断里,关于变量是否添加双引号、本质上不一样的。。。。
0.学前预览
先看下,系统自带的脚本,shell的语法,在你学习了之后,就看得懂了,也可以模仿着写。
#!/bin/sh
printf "Are you sure you want to uninstall Webmin? (y/n) : "
read answer
printf "\n"
if [ "$answer" = "y" ]; then
echo "Removing Webmin package .."
rm -f /usr/share/webmin/authentic-theme/manifest-*
dpkg --remove --force-depends webmin
systemctlcmd=`which systemctl 2>/dev/null`
if [ -x "$systemctlcmd" ]; then
$systemctlcmd stop webmin >/dev/null 2>&1 </dev/null
rm -f /lib/systemd/system/webmin.service
$systemctlcmd daemon-reload
fi
echo ".. done"
fi
https://github.com/guohongze/adminset/blob/master/install/server/auto_install.sh
1.基于文件进行条件判断
我们这里先来学习这个条件判断的语法,下一步才进入if语句的学习。
常用参数
条件判断内容 | 操作符 | 示例 | 说明 |
---|---|---|---|
文件是否存在 | -e | if [ -e file.txt ]; then echo "文件存在"; fi |
如果file.txt 存在,条件为真,执行echo 命令 |
是否为普通文件 | -f | if [ -f normal_file ]; then echo "是普通文件"; fi |
如果normal_file 是普通文件(非目录、设备文件等),条件为真 |
是否为目录 | -d | if [ -d dir ]; then echo "是目录"; fi |
如果dir 是目录,条件为真 |
是否为符号链接 | -L | if [ -L link ]; then echo "是符号链接"; fi |
如果link 是符号链接,条件为真 |
是否可读 | -r | if [ -r file_path ]; then echo "可读"; fi |
对于file_path 指定的文件,如果有可读权限,条件为真 |
是否可写 | -w | if [ -w file_path ]; then echo "可写"; fi |
如果file_path 有可写权限,条件为真 |
是否可执行 | -x | if [ -x file_path ]; then echo "可执行"; fi |
如果file_path 有可执行权限,条件为真 |
文件1是否比文件2新 | -nt | if [ file1 -nt file2 ]; then echo "文件1比文件2新"; fi |
比较两个文件的新旧,文件1新则条件为真 |
文件1是否比文件2旧 | -ot | if [ file1 -ot file2 ]; then echo "文件1比文件2旧"; fi |
比较两个文件的新旧,文件1旧则条件为真 |
更多参数
做好笔记即可,看来回来查查
test 命令最短的定义可能是评估一个表达式;如果条件为真,则返回一个 0 值。如果表达式不为真,则返回一个大于 0 的值 — 也可以将其称为假值。检查最后所执行命令的状态的最简便方法是使用 $? 值。
参数:
1. 关于某个文件名的『类型』侦测(存在与否),如 test -e filename
-e 该『文件名』是否存在?(常用)
-f 该『文件名』是否为文件(file)?(常用)
-d 该『文件名』是否为目录(directory)?(常用)
-b 该『文件名』是否为一个 block device 装置?
-c 该『文件名』是否为一个 character device 装置?
-S 该『文件名』是否为一个 Socket 文件?
-p 该『文件名』是否为一个 FIFO (pipe) 文件?
-L 该『文件名』是否为一个连结档?
2. 关于文件的权限侦测,如 test -r filename
-r 侦测该文件名是否具有『可读』的属性?
-w 侦测该文件名是否具有『可写』的属性?
-x 侦测该文件名是否具有『可执行』的属性?
-u 侦测该文件名是否具有『SUID』的属性?
-g 侦测该文件名是否具有『SGID』的属性?
-k 侦测该文件名是否具有『Sticky bit』的属性?
-s 侦测该文件名是否为『非空白文件』?
3. 两个文件之间的比较,如: test file1 -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file2 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
4. 关于两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
5. 判定字符串的数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为 false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
结合test命令
test命令的基本介绍
test
命令是一个在Bash中进行条件测试的内置命令,它和使用[ ]
进行条件测试的功能基本相同,只是语法略有不同。实际上,在使用[ ]
时,Bash会将其解释为test
命令,例如[ -e file.txt ]
等价于test -e file.txt
。
使用test进行文件测试
- 文件存在测试:
if test -e file.txt; then echo "文件存在。" else echo "文件不存在。" fi
- 这个例子使用
test -e file.txt
来检查file.txt
是否存在。如果存在,将打印“文件存在。”,否则打印“文件不存在。”。 - 文件类型测试:
if test -f normal_file; then echo "这是一个普通文件。" else echo "这不是一个普通文件。" fi
- 这里使用
test -f
来检查normal_file
是否是普通文件。同样,你可以使用test -d
来检查是否是目录,test -L
来检查是否是符号链接等。 - 文件权限测试:
if test -r file_path; then echo "文件具有可读权限。" else echo "文件没有可读权限。" fi
- 上述代码使用
test -r
来检查file_path
是否具有可读权限。类似地,可以使用test -w
检查可写权限,test -x
检查可执行权限。
- 文件存在测试:
使用test进行字符串测试
- 字符串相等测试:
str1="hello" str2="hello" if test "$str1" = "$str2"; then echo "两个字符串相等。" else echo "两个字符串不相等。" fi
- 这里使用
test "$str1" = "$str2"
来判断两个字符串是否相等,确保使用双引号将变量括起来,以避免空变量带来的问题。 - 字符串长度测试(间接方法):
str="abcdefg" if test ${#str} -gt 5; then echo "字符串长度大于 5。" else echo "字符串长度小于或等于 5。" fi
- 通过
${#str}
获取字符串的长度,并使用test
和数字比较操作符(如-gt
)来判断字符串长度是否大于 5。
- 字符串相等测试:
使用test进行数字测试
- 数字相等测试:
num1=10 num2=20 if test $num1 -eq $num2; then echo "两个数字相等。" else echo "两个数字不相等。" fi
- 这里使用
test $num1 -eq $num2
来检查两个数字是否相等。你可以使用-ne
(不等于)、-lt
(小于)、-gt
(大于)、-le
(小于等于)、-ge
(大于等于)等操作符进行不同的数字比较。
- 数字相等测试:
test命令的逻辑操作符
- 逻辑与:使用
-a
进行逻辑与操作。例如,要检查文件是否既存在又可读:if test -e file.txt -a -r file.txt; then echo "文件存在且可读。" else echo "文件不存在或不可读。" fi
- 此代码使用
test -e file.txt -a -r file.txt
来判断文件是否存在且可读。只有当文件存在并且有可读权限时,条件才为真。 - 逻辑或:使用
-o
进行逻辑或操作。例如,检查文件是否可写或可执行:if test -w file.txt -o -x file.txt; then echo "文件可写或可执行。" else echo "文件既不可写也不可执行。" fi
- 上述代码使用
test -w file.txt -o -x file.txt
来判断文件是否可写或可执行。只要文件具有可写权限或可执行权限中的一个,条件就为真。 - 逻辑非:使用
!
进行逻辑非操作。例如,检查文件是否不存在:if test! -e file.txt; then echo "文件不存在。" else echo "文件存在。" fi
- 这里使用
test! -e file.txt
来判断文件是否不存在。如果文件不存在,条件为真,将打印“文件不存在。”。
- 逻辑与:使用
test命令的注意事项
- 对于复杂的条件测试,使用
test
命令时,要注意操作符的顺序和逻辑的正确性。 - 当使用多个条件时,需要根据实际需求合理运用逻辑操作符,避免逻辑混乱。
- 在组合使用不同的条件测试时,最好使用括号和转义字符来确保条件的清晰和准确,例如:
if test \( -e file1.txt -a \( -r file1.txt -o -w file1.txt \) \); then echo "文件存在,并且可读写。" else echo "文件不存在或不可读写。" fi
- 在这个例子中,使用
\(
和\)
对条件进行分组,以确保逻辑的清晰,先判断文件是否存在,然后判断是否可读或可写。同时使用转义字符\
来避免括号被错误解释。
- 对于复杂的条件测试,使用
用test 条件语句
为真
[root@yuchaoit666 ~/p3-shell]#touch yuchaoit.log
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#test -f "yuchaoit.log" && echo "true" || echo "false"
true
为假
[root@yuchaoit666 ~/p3-shell]#test -f "666yuchaoit.log" && echo "true" || echo "false"
false
写法2
用[ 条件语句 ]
[root@yuchaoit666 ~/p3-shell]#[ -f "666yuchaoit.log" ] && echo "true" || echo "false"
false
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#[ -f "yuchaoit.log" ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~/p3-shell]#
测试常用条件参数
俩写法
1.判断ansible的主机清单文件是否存在,不存在提示用户先创建再使用ansible命令。
----------------------------------------------------------------------------------
# 普通文件
[ -f /etc/ansible/hosts ] && echo "主机清单hosts文件存在..." || echo "先去创建主机清单hsots文件!!"
----------------------------------------------------------------------------------
# 文件存在
[ -e /etc/ansible/hosts ] && echo "主机清单hosts文件存在..." || echo "先去创建主机清单hsots文件!!"
----------------------------------------------------------------------------------
# 注意坑,root怕你这权限吗?
[ -r /etc/ansible/hosts ] && echo "主机清单hosts允许读取!!" || echo "无权读取!!"
[ -w /etc/ansible/hosts ] && echo "主机清单hosts允许写入!!" || echo "无权写入!!"
[ -x /etc/ansible/hosts ] && echo "主机清单hosts允许执行!!" || echo "无权执行!!"
----------------------------------------------------------------------------------
# 文件里有内容吗?
# 试试
>/etc/ansible/hosts
# 条件判断
[ -s /etc/ansible/hosts ] && echo "hosts清单文件有内容!!" || echo "hosts文件为空,请写入!!"
----------------------------------------------------------------------------------
几个特殊文件,看看有内容吗
root@yuchaoit666 ~/p3-shell]#[ -s /dev/zero ] && echo true || echo false
false
[root@yuchaoit666 ~/p3-shell]#[ -s /dev/null ] && echo true || echo false
false
[root@yuchaoit666 ~/p3-shell]#[ -s /etc/passwd ] && echo true || echo false
true
----------------------------------------------------------------------------------
test命令写法
[root@yuchaoit666 ~/p3-shell]#test -s /etc/passwd && echo true || echo false
true
[root@yuchaoit666 ~/p3-shell]#test -s /etc/passwddddd && echo true || echo false
false
条件测试,综合案例
以下是一个使用bash进行条件测试的综合案例,包含了多种条件测试选项,如文件测试、字符串测试和数值测试。
#!/bin/bash
# 文件测试
if [ -e "testfile.txt" ]; then
echo "文件 testfile.txt 存在。"
else
echo "文件 testfile.txt 不存在。"
fi
# 目录测试
if [ -d "testdir" ]; then
echo "目录 testdir 存在。"
else
echo "目录 testdir 不存在。"
fi
# 字符串测试
str1="hello"
str2="world"
if [ "$str1" == "$str2" ]; then
echo "字符串 str1 和 str2 相等。"
else
echo "字符串 str1 和 str2 不相等。"
fi
if [ -z "$str1" ]; then
echo "字符串 str1 长度为 0。"
else
echo "字符串 str1 长度不为 0。"
fi
# 数值测试
num1=10
num2=20
if [ $num1 -eq $num2 ]; then
echo "num1 等于 num2。"
elif [ $num1 -lt $num2 ]; then
echo "num1 小于 num2。"
else
echo "num1 大于 num2。"
fi
# 组合条件测试
if [ -e "testfile.txt" ] && [ -d "testdir" ]; then
echo "文件 testfile.txt 存在且目录 testdir 存在。"
elif [ -e "testfile.txt" ] || [ -d "testdir" ]; then
echo "文件 testfile.txt 存在或目录 testdir 存在。"
else
echo "文件 testfile.txt 和目录 testdir 都不存在。"
fi
代码解释
文件测试:
[ -e "testfile.txt" ]
:检查文件testfile.txt
是否存在。-e
选项用于测试文件是否存在。[ -d "testdir" ]
:检查目录testdir
是否存在。-d
选项用于测试目录是否存在。
字符串测试:
[ "$str1" = "$str2" ]
:比较字符串str1
和str2
是否相等。[ -z "$str1" ]
:检查字符串str1
的长度是否为 0。-z
选项用于测试字符串长度是否为 0。
数值测试:
[ $num1 -eq $num2 ]
:检查num1
是否等于num2
。-eq
是数值相等的测试选项。[ $num1 -lt $num2 ]
:检查num1
是否小于num2
。-lt
是小于的测试选项。
组合条件测试:
[ -e "testfile.txt" ] && [ -d "testdir" ]
:使用&&
逻辑与运算符,当文件testfile.txt
存在且目录testdir
存在时执行相应代码。[ -e "testfile.txt" ] || [ -d "testdir" ]
:使用||
逻辑或运算符,当文件testfile.txt
存在或目录testdir
存在时执行相应代码。
使用说明
- 将上述代码保存为一个文件,例如
test.sh
。 - 打开终端,使用
chmod +x test.sh
为文件添加执行权限。 - 运行脚本:
./test.sh
。
这个案例涵盖了bash中常见的条件测试类型,包括文件、目录、字符串和数值的测试,以及逻辑运算符的使用,可以帮助你理解和掌握bash中的条件测试操作。
2.基于整数判断
比较操作 | 操作符 | 示例 | 说明 |
---|---|---|---|
相等 | -eq | if test $num1 -eq $num2; then echo "相等"; fi |
当 $num1 等于 $num2 时,条件为真 |
不相等 | -ne | if test $num1 -ne $num2; then echo "不相等"; fi |
当 $num1 不等于 $num2 时,条件为真 |
小于 | -lt | if test $num1 -lt $num2; then echo "小于"; fi |
当 $num1 小于 $num2 时,条件为真 |
大于 | -gt | if test $num1 -gt $num2; then echo "大于"; fi |
当 $num1 大于 $num2 时,条件为真 |
小于等于 | -le | if test $num1 -le $num2; then echo "小于等于"; fi |
当 $num1 小于或等于 $num2 时,条件为真 |
大于等于 | -ge | if test $num1 -ge $num2; then echo "大于等于"; fi |
当 $num1 大于或等于 $num2 时,条件为真 |
在使用上述数值比较操作符时,以下是一些需要注意的点:
- 确保比较的是数字,而不是字符串。例如,在使用
test
或[ ]
进行条件判断时,$num1
和$num2
应该是数字或可被解析为数字的变量。 - 示例中的
test
命令也可以用[ ]
代替,如if [ $num1 -eq $num2 ]; then echo "相等"; fi
。 - 对于复杂的逻辑判断,可以结合逻辑运算符,例如:
此代码使用num1=5 num2=10 num3=15 if [ $num1 -lt $num2 -a $num2 -lt $num3 ]; then echo "num1 < num2 < num3" fi
-a
逻辑与运算符来判断num1
是否小于num2
并且num2
是否小于num3
。
这些数值比较操作符在脚本编写中非常有用,例如:
# 检查系统负载是否过高
load=$(uptime | awk '{print $10}' | cut -d. -f1)
if [ $load -gt 5 ]; then
echo "系统负载过高!"
else
echo "系统负载正常。"
fi
在这个脚本中,使用 uptime
命令获取系统负载,通过 awk
和 cut
处理输出,最后使用 -gt
操作符来判断系统负载是否超过 5,根据结果输出相应信息。
此外,还可以在循环和函数中使用数值判断,例如:
# 打印 1 到 10 的偶数
for ((i=1; i<=10; i++)); do
if [ $((i % 2)) -eq 0 ]; then
echo $i
fi
done
此代码使用 for
循环从 1 到 10 遍历数字,通过 $((i % 2)) -eq 0
判断 i
除以 2 的余数是否为 0,若是则打印该数字,实现打印偶数的功能。
条件语法
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
猜数字脚本
以下是一个简单的Bash猜数字比大小脚本:
猜数字,让用户输入一个数字,你给出一个随机数,猜对游戏结束,猜错给出提示。
限制10次?怎么做?
[root@www.yuchaoit.cn ~]$cat guess_num.sh
#!/bin/bash
target_num=$(( $RANDOM%100 + 1 ))
echo "欢迎使用猜数字游戏---v1版"
guess=0
while [ $guess -ne $target_num ]
do
read -p "输入你的数字:" guess
# 判断输入是否合法,为纯数字
if [[ ! $guess =~ ^[0-9]+$ ]]
then
echo "必须是纯数字,重写!"
guess=0
continue
fi
# 输入正确,是纯数字,数字判断,给一些提示
if [ $guess -lt $target_num ];then
echo "太小了,往大了猜!"
elif [ $guess -gt $target_num ];then
echo "太大了!往小了再猜!!!!"
else
echo "恭喜你,牛啊老弟"
fi
done
[root@www.yuchaoit.cn ~]$
# 添加功能,v2,限制只能猜10次,并且每次提示,猜测第几次。
代码解释和使用说明:
target_number=$((RANDOM % 100 + 1))
:使用RANDOM
环境变量生成一个随机数,RANDOM
是一个Bash内置的随机数生成器,范围是 0 到 32767。通过% 100 + 1
运算将其范围限制在 1 到 100 之间。guess=-1
:初始化用户的猜测数字为 -1,这个值会在用户开始输入数字后更新。while [ $guess -ne $target_number ]; do
:使用while
循环,只要用户的猜测不等于目标数字,就会一直循环。read -p "请输入你的猜测: " guess
:使用read
命令提示用户输入一个数字,并将用户输入存储在guess
变量中。if [[! $guess =~ ^[0-9]+$ ]]; then
:使用正则表达式^[0-9]+$
检查用户输入是否为纯数字,如果不是,则提示用户输入有效数字并使用continue
继续下一次循环。if [ $guess -lt $target_number ]; then
和if [ $guess -gt $target_number ]; then
:使用条件判断,如果用户的猜测小于或大于目标数字,分别给出相应的提示。else
部分:当用户猜对时,打印恭喜信息并结束循环。
这个脚本的使用方法很简单,你只需要将其保存为一个文件(例如 guess_game.sh
),并赋予执行权限(chmod +x guess_game.sh
),然后运行该文件(./guess_game.sh
),即可开始猜数字游戏。
你可以根据需要对这个脚本进行扩展,例如添加猜测次数限制,当超过一定次数还未猜对时,游戏结束;或者增加不同的难度级别,改变随机数的范围等。
案例
猜数字比大小
猜数字大小程序开发(初版,还有很多bug!一步步优化!)
cat > num.sh<<'EOF'
# 结果
result=18
# 用户输入
read -p "请输入数字,猜大小:" num
if [ $result -eq $num ];then
echo "猜对啦!你可真nb!"
elif [ $result -gt $num ];then
echo "太小了,再猜!"
elif [ $result -lt $num ];then
echo "太大了,再猜!"
fi
EOF
执行
比较数字大小,美化结果
cat > beautiful_num.sh<<'EOF'
# 加载美化脚本
source /etc/init.d/functions
# 接收输入
read -p "please input num1:" num1
read -p "please input num2:" num2
# 条件判断测试
# 等于
[ $num1 -eq $num2 ] && action "-eq 等于OK" /bin/true || action "-eq NO" /bin/false
# 不等于
[ $num1 -ne $num2 ] && action "-ne 不等于OK" /bin/true || action "-ne NO" /bin/false
# 大于
[ $num1 -gt $num2 ] && action "-gt 大于OK" /bin/true || action "-gt NO" /bin/false
# 小于
[ $num1 -lt $num2 ] && action "-lt 小于OK" /bin/true || action "-lt NO" /bin/false
# 大于等于
[ $num1 -ge $num2 ] && action "-ge 大于等于OK" /bin/true || action "-ge NO" /bin/false
# 小于等于
[ $num1 -le $num2 ] && action "-le 小于等于OK" /bin/true || action "-le NO" /bin/false
EOF
扩展条件测试
在Bash中,[]
和[[]]
都是用于条件测试和模式匹配的结构,但它们在功能和使用上有一些区别,以下是详细解释:
[]
(test命令的简化形式)
基本用途
- 用于进行各种条件测试,例如检查文件属性、比较数值、判断字符串是否为空或相等。例如,
[ -f file.txt ]
用于检查file.txt
是否为普通文件,[ 5 -gt 3 ]
用于判断5是否大于3。
- 用于进行各种条件测试,例如检查文件属性、比较数值、判断字符串是否为空或相等。例如,
操作符使用
- 在
[]
中使用比较操作符时,需要注意操作符和操作数之间要有空格分隔,否则会导致错误。例如,正确的写法是[ $a -eq 10 ]
,而不是[ $a -eq 10 ]
。 - 对于字符串比较,
[]
使用=
和!=
来判断是否相等或不相等。例如,[ "$str" = "hello" ]
。
- 在
逻辑操作
- 可以使用
-a
(与)和-o
(或)来进行逻辑运算。例如,[ $a -gt 5 -a $a -lt 10 ]
表示$a
大于5且小于10。
- 可以使用
[[]]
(扩展的条件测试)
- 基本用途
- 也是用于条件测试和模式匹配,功能比
[]
更强大,是Bash的扩展特性。
- 也是用于条件测试和模式匹配,功能比
- 操作符使用
- 支持更多的比较操作符,例如
>
、<
在[[]]
中可以直接用于字符串比较,并且按照字典序进行比较。例如,[[ "abc" < "abd" ]]
返回真。
- 支持更多的比较操作符,例如
- 逻辑操作
- 可以使用
&&
(与)和||
(或)进行逻辑运算,这与[]
中的-a
和-o
类似,但在使用上可能更符合习惯。例如,[[ $a -gt 5 && $a -lt 10 ]]
。
- 可以使用
- 模式匹配
- 支持更高级的模式匹配功能,如正则表达式匹配。例如,
[[ "hello world" =~ ^hello.* ]]
可以匹配以hello
开头的字符串。 - 还支持
=~
操作符用于正则表达式匹配,这在处理复杂的字符串匹配场景时非常有用。
- 支持更高级的模式匹配功能,如正则表达式匹配。例如,
- 变量扩展
- 在
[[]]
中,变量扩展更加灵活。例如,[[ $str == he* ]]
可以正确匹配以he
开头的字符串,而在[]
中可能需要使用[ "${str#he*}"!= "$str" ]
来实现类似功能。
- 在
总结来说,[]
是比较传统和基本的条件测试结构,适用于简单的条件判断和测试。[[]]
是Bash的扩展特性,提供了更强大、更灵活的功能,特别是在字符串处理和模式匹配方面,更适合复杂的条件判断和脚本编写。在实际使用中,可以根据具体需求选择合适的结构。
练习题
判断整数
以下是一个Bash脚本,用于判断用户输入的内容是否为整数:
#!/bin/bash
# 提示用户输入一个数
read -p "请输入一个数: " input
# 使用正则表达式来判断输入是否为整数
if [[ $input =~ ^[0-9]+$ ]]; then
echo "输入的是整数。"
else
echo "输入的不是整数。"
fi
代码解释和使用说明:
read -p "请输入一个数: " input
:使用read
命令提示用户输入一个数,并将用户输入存储在input
变量中。if [[ $input =~ ^[0-9]+$ ]]; then
:这里使用了双中括号[[ ]]
中的=~
运算符,用于进行正则表达式匹配。^[0-9]+$
是一个正则表达式,其中:^
表示匹配字符串的开始。[0-9]
表示匹配数字 0 到 9 中的任意一个。+
表示匹配前面的元素(即数字)一次或多次。$
表示匹配字符串的结束。
- 所以,这个正则表达式整体的含义是:从字符串的开始到结束,全部由数字组成,这就是判断输入是否为整数的依据。
echo "输入的是整数。"
:如果输入匹配上述正则表达式,说明输入的是整数,打印相应的信息。else
部分:如果输入不匹配,打印“输入的不是整数。”。
使用该脚本的步骤如下:
- 将上述代码保存为一个文件,例如
check_integer.sh
。 - 为该文件添加执行权限,使用命令
chmod +x check_integer.sh
。 - 运行该脚本,使用命令
./check_integer.sh
。
你可以在这个基础上进行扩展,例如将这个判断封装在一个函数中,方便在其他脚本中调用,代码如下:
#!/bin/bash
# 定义一个函数来判断输入是否为整数
function is_integer() {
local input="$1"
if [[ $input =~ ^[0-9]+$ ]]; then
return 0
else
return 1
fi
}
# 提示用户输入一个数
read -p "请输入一个数: " input
# 调用函数进行判断
if is_integer "$input"; then
echo "输入的是整数。"
else
echo "输入的不是整数。"
fi
代码解释和使用说明:
function is_integer() {...}
:定义了一个名为is_integer
的函数,它接受一个参数$1
,将其存储在local input="$1"
中。- 如果输入匹配整数的正则表达式,函数使用
return 0
表示输入是整数。 - 否则,使用
return 1
表示输入不是整数。
- 如果输入匹配整数的正则表达式,函数使用
read -p "请输入一个数: " input
:提示用户输入一个数,并存储在input
变量中。if is_integer "$input"; then
:调用is_integer
函数,并根据函数的返回值进行判断,如果返回值为 0,则输入是整数;如果返回值为 1,则输入不是整数。
通过将判断逻辑封装在函数中,可以提高代码的复用性和可维护性,方便在其他脚本中使用该函数进行整数判断。
判断参数个数
以下是一个简单的Bash脚本,用于判断传递给脚本的参数个数:
#!/bin/bash
# 获取传递给脚本的参数个数
num_params=$#
# 对参数个数进行判断
if [ $num_params -eq 0 ]; then
echo "没有传递任何参数。"
elif [ $num_params -eq 1 ]; then
echo "传递了一个参数。"
elif [ $num_params -eq 2 ]; then
echo "传递了两个参数。"
else
echo "传递了多个参数(大于 2 个)。"
fi
代码解释和使用说明:
num_params=$#
:使用$#
特殊变量来获取传递给脚本的参数的数量。在Bash中,$#
表示传递给脚本的参数的个数。if [ $num_params -eq 0 ]; then
:使用条件判断来检查参数的数量是否等于 0。- 如果参数数量等于 0,打印“没有传递任何参数。”。
elif [ $num_params -eq 1 ]; then
:如果参数数量等于 1,打印“传递了一个参数。”。elif [ $num_params -eq 2 ]; then
:如果参数数量等于 2,打印“传递了两个参数。”。else
部分:如果参数数量大于 2,打印“传递了多个参数(大于 2 个)。”。
使用该脚本的步骤如下:
- 将上述代码保存为一个文件,例如
check_param_count.sh
。 - 为该文件添加执行权限,使用命令
chmod +x check_param_count.sh
。 - 可以有以下几种运行方式:
- 不传递参数:
./check_param_count.sh
,会输出“没有传递任何参数。”。 - 传递一个参数:
./check_param_count.sh param1
,会输出“传递了一个参数。”。 - 传递两个参数:
./check_param_count.sh param1 param2
,会输出“传递了两个参数。”。 - 传递多个参数:
./check_param_count.sh param1 param2 param3
,会输出“传递了多个参数(大于 2 个)。”。
- 不传递参数:
你可以根据自己的需求对该脚本进行扩展,例如:
- 当参数数量不符合要求时,给出错误提示并退出脚本。
- 根据不同的参数数量执行不同的操作,代码示例如下:
```bash
!/bin/bash
获取传递给脚本的参数个数
num_params=$#
对参数个数进行判断
if [ $num_params -eq 0 ]; then echo "没有传递任何参数,脚本需要至少一个参数。" exit 1 elif [ $num_params -eq 1 ]; then echo "传递了一个参数,执行操作 A。"
# 这里可以添加对一个参数的具体操作
param1=$1
echo "参数是:$param1"
elif [ $num_params -eq 2 ]; then echo "传递了两个参数,执行操作 B。"
# 这里可以添加对两个参数的具体操作
param1=$1
param2=$2
echo "参数是:$param1 和 $param2"
else echo "传递了多个参数(大于 2 个),执行操作 C。"
# 这里可以添加对多个参数的具体操作
echo "所有参数:$@"
fi
**代码解释和使用说明**:
- `exit 1`:当没有传递任何参数时,使用 `exit 1` 退出脚本,并返回错误代码 1,表示发生了错误。
- `param1=$1` 和 `param2=$2`:将第一个和第二个参数存储在变量 `param1` 和 `param2` 中,方便后续操作。
- `echo "所有参数:$@"`:使用 `$@` 特殊变量可以获取传递给脚本的所有参数列表,在参数数量大于 2 时打印出所有参数。
这样可以让脚本根据不同的参数数量做出不同的处理,使脚本更加灵活和实用。
### 判断用户的密码是否符合6位
> 方案1:利用变量的子字符串功能,判断字符串长度`${#变量}`
cat > user_pwd.sh<<'EOF' read -p "please input your pwd:" pwd
条件判断处理,利用变量的子字符串功能
[ ${#pwd} -ne 6 ] && echo "错误!密码必须是6位" || echo "正确!您的密码是:${pwd}" EOF
> 方案2:使用wc -L 参数
cat > pwd.sh <<'EOF' read -p "please input your pwd:" pwd
密码长度校验
pwd_len=$(echo $pwd|wc -L) [ $pwd_len -ne 6 ] && echo "错误!密码必须是6位" || echo "正确!您的密码是:${pwd}" EOF
### 用户登录脚本
以下是一个简单的Bash用户登录脚本示例,该脚本会从用户那里获取用户名和密码,并进行简单的验证:
```bash
#!/bin/bash
# 预设的用户名和密码(实际应用中应该使用更安全的存储方式,如数据库)
correct_username="admin"
correct_password="password123"
# 提示用户输入用户名和密码
read -p "请输入用户名: " input_username
read -s -p "请输入密码: " input_password
echo
# 进行验证
if [ "$input_username" = "$correct_username" ] && [ "$input_password" = "$correct_password" ]; then
echo "登录成功!"
else
echo "用户名或密码错误,请重试。"
fi
代码解释和使用说明:
correct_username="admin"
和correct_password="password123"
:设置了预设的用户名和密码。在实际应用中,这些信息应该存储在更安全的地方,比如数据库,而不是硬编码在脚本中。read -p "请输入用户名: " input_username
:使用read
命令提示用户输入用户名,并将其存储在input_username
变量中。read -s -p "请输入密码: " input_password
:使用read -s
命令提示用户输入密码,-s
选项会隐藏用户输入,避免密码显示在屏幕上。echo
:添加一个空的echo
语句,使输入密码后光标移到下一行,以保持输出的美观。if [ "$input_username" = "$correct_username" ] && [ "$input_password" = "$correct_password" ]; then
:使用if
语句结合逻辑与运算符&&
来检查输入的用户名和密码是否与预设的匹配。[ "$input_username" = "$correct_username" ]
:检查用户名是否正确。[ "$input_password" = "$correct_password" ]
:检查密码是否正确。- 只有当用户名和密码都正确时,才会输出“登录成功!”。
else
部分:如果用户名或密码错误,输出“用户名或密码错误,请重试。”。
以下是该脚本的使用方法:
- 将上述代码保存为一个文件,例如
login_script.sh
。 - 为该文件添加执行权限,使用命令
chmod +x login_script.sh
。 - 运行该脚本,使用命令
./login_script.sh
。
为了提高该脚本的安全性和实用性,你可以进行以下扩展:
- 添加用户输入验证:确保用户输入不为空,避免输入错误。
```bash
!/bin/bash
预设的用户名和密码(实际应用中应该使用更安全的存储方式,如数据库)
correct_username="admin" correct_password="password123"
提示用户输入用户名和密码
read -p "请输入用户名: " input_username read -s -p "请输入密码: " input_password echo
验证输入是否为空
if [ -z "$input_username" ] || [ -z "$input_password" ]; then echo "用户名或密码不能为空,请重试。" exit 1 fi
进行验证
if [ "$input_username" = "$correct_username" ] && [ "$input_password" = "$correct_password" ]; then echo "登录成功!" else echo "用户名或密码错误,请重试。" fi
**代码解释和使用说明**:
- `if [ -z "$input_username" ] || [ -z "$input_password" ]; then`:使用 `-z` 选项检查用户名或密码是否为空。
- `-z` 用于检查字符串长度是否为零,如果为空,输出错误信息并使用 `exit 1` 退出脚本。
- **限制登录尝试次数**:限制用户尝试登录的次数,防止暴力破解。
```bash
#!/bin/bash
# 预设的用户名和密码(实际应用中应该使用更安全的存储方式,如数据库)
correct_username="admin"
correct_password="password123"
max_attempts=3
attempts=0
# 循环进行登录尝试
while [ $attempts -lt $max_attempts ]; do
# 提示用户输入用户名和密码
read -p "请输入用户名: " input_username
read -s -p "请输入密码: " input_password
echo
# 验证输入是否为空
if [ -z "$input_username" ] || [ -z "$input_password" ]; then
echo "用户名或密码不能为空,请重试。"
continue
fi
# 进行验证
if [ "$input_username" = "$correct_username" ] && [ "$input_password" = "$correct_password" ]; then
echo "登录成功!"
exit 0
else
echo "用户名或密码错误,请重试。"
attempts=$((attempts + 1))
fi
done
echo "超过最大尝试次数,请稍后再试。"
exit 1
代码解释和使用说明:
max_attempts=3
:设置最大尝试次数为 3 次。attempts=0
:初始化尝试次数为 0。while [ $attempts -lt $max_attempts ]; do
:使用while
循环,只要尝试次数小于最大尝试次数,就允许用户继续尝试登录。attempts=$((attempts + 1))
:每次尝试失败后,将尝试次数加 1。echo "超过最大尝试次数,请稍后再试。"
:当尝试次数超过最大次数时,输出错误信息并使用exit 1
退出脚本。
这些扩展可以使登录脚本更加安全和完善,你可以根据具体需求进一步调整和扩展该脚本。
3.基于字符串判断
比较操作 | 操作符 | 示例 | 说明 |
---|---|---|---|
相等 | = 或 == | if [ "$str1" = "$str2" ]; then echo "相等"; fi |
当 $str1 等于 $str2 时,条件为真,使用 == 操作符在某些情况下也可行,但 = 更常用且符合标准。使用双引号包裹变量,可防止变量为空时的语法错误。 |
不相等 | != | if [ "$str1"!= "$str2" ]; then echo "不相等"; fi |
当 $str1 不等于 $str2 时,条件为真。 |
长度为零 | -z | if [ -z "$str" ]; then echo "字符串长度为零"; fi |
若 $str 的长度为 0,条件为真。常用于检查变量是否为空。 |
长度不为零 | -n | if [ -n "$str" ]; then echo "字符串长度不为零"; fi |
若 $str 的长度不为 0,条件为真。可用于检查变量是否包含有效内容。 |
以下是使用这些操作符的示例脚本:
#!/bin/bash
str1="hello"
str2="world"
str3=""
# 相等比较
if [ "$str1" = "$str2" ]; then
echo "str1 等于 str2"
else
echo "str1 不等于 str2"
fi
# 不相等比较
if [ "$str1"!= "$str2" ]; then
echo "str1 不等于 str2"
else
echo "str1 等于 str2"
fi
# 长度为零检查
if [ -z "$str3" ]; then
echo "str3 长度为零"
else
echo "str3 长度不为零"
fi
# 长度不为零检查
if [ -n "$str1" ]; then
echo "str1 长度不为零"
else
echo "str1 长度为零"
fi
代码解释和使用说明:
if [ "$str1" = "$str2" ]; then...
:使用=
操作符检查str1
和str2
是否相等,由于它们不相等,将输出“str1 不等于 str2”。if [ "$str1"!= "$str2" ]; then...
:使用!=
操作符检查str1
和str2
是否不相等,将输出“str1 不等于 str2”。if [ -z "$str3" ]; then...
:使用-z
操作符检查str3
的长度是否为零,由于str3
为空字符串,将输出“str3 长度为零”。if [ -n "$str1" ]; then...
:使用-n
操作符检查str1
的长度是否不为零,由于str1
不为空,将输出“str1 长度不为零”。
在实际的脚本编写中,这些操作符的使用非常灵活,例如:
#!/bin/bash
# 检查环境变量是否设置
if [ -z "$JAVA_HOME" ]; then
echo "JAVA_HOME 环境变量未设置,请设置该环境变量。"
else
echo "JAVA_HOME 已设置:$JAVA_HOME"
fi
# 检查用户输入是否为指定字符串
read -p "请输入一个字符串: " user_input
if [ "$user_input" = "quit" ]; then
echo "用户选择退出。"
exit 0
else
echo "用户输入:$user_input"
fi
代码解释和使用说明:
if [ -z "$JAVA_HOME" ]; then...
:检查JAVA_HOME
环境变量是否未设置,若未设置则给出提示。read -p "请输入一个字符串: " user_input
:提示用户输入一个字符串并存储在user_input
中。if [ "$user_input" = "quit" ]; then...
:检查用户输入是否为“quit”,若是则退出脚本,否则输出用户输入的内容。
此外,还可以在复杂的逻辑中使用这些操作符,如:
#!/bin/bash
str1="yes"
str2="no"
str3="maybe"
# 复杂逻辑判断
if [ "$str1" = "yes" ] && [ -n "$str2" ] || [ "$str3" = "maybe" ]; then
echo "满足复杂逻辑条件"
else
echo "不满足复杂逻辑条件"
fi
代码解释和使用说明:
if [ "$str1" = "yes" ] && [ -n "$str2" ] || [ "$str3" = "maybe" ]; then...
:使用逻辑与&&
和逻辑或||
运算符。- 当
str1
等于“yes”且str2
长度不为零,或者str3
等于“maybe”时,条件为真,将输出“满足复杂逻辑条件”。
- 当
这些字符串比较操作符和逻辑运算符的组合可以帮助你在Bash脚本中进行丰富的条件判断,以实现各种功能。
系统自带脚本参考
以及一段关于mysql的脚本
233 # pid-file exists, the server process doesn't.
234 # it must've crashed, and mysqld_safe will restart it
235 if test -n "$crash_protection"; then
236 crash_protection=""
237 sleep 5
238 continue # Check again.
239 fi
这里就是判断,当该crash_protection变量非空时,将其置空
这里的逻辑我们不用过多关注,从注释可以得知
该代码作用是,当mysql的pid-file存在,但是mysql进程不存在,这就证明mysql异常挂掉了,mysql应该重启。
练习
简单等于、不等于符号
[root@yuchaoit666 ~]#[ 10 == 10 ] && echo "yes" || echo "no"
yes
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 10 != 10 ] && echo "yes" || echo "no"
no
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 10 != 5 ] && echo "yes" || echo "no"
yes
条件参数-z和-n相反测试
[root@yuchaoit666 ~]#name="yuchao666"
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
# -z 字符串为空,才为真
[root@yuchaoit666 ~]#[ -z $name ] && echo "true" || echo "false"
false
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -z $name2 ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -n $name ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -n $name2 ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#
模拟开发登录程序
接收用户输入,和密码文件对比,判断是否登录成功。
现有账号密码
yuchao01
chaoge666
cat >user_login.sh<<'EOF'
read -p "please input username:" username
read -p "please input pwd:" pwd
[ $username == "yuchao01" -a $pwd == "chaoge666" ] && echo "登录成功" || echo "账号密码错误"
EOF
4. 逻辑操作符
逻辑运算,也就是生活里的 真、假概念
! 取反,也就是结果相反的值
-a 是“与”的意思(等同 && 和and),要求,左右两个逻辑值都为真,结果才为真,否则为假
-o 是或者的意思,(or 和 ||),左右两个逻辑,只要有一个真,结果就为真
结果为真,对应计算机数字是1
结果为假,计算机数字为0
注意:选用不同的语法,对应的测试符号不一样!!!
参数 | 解释 | 案例 |
---|---|---|
-a | 左右两边条件同时为真时,为true | [ 6 -eq 6 -a 8 -gt 3 ] |
-o | 左右两边条件有一个为真,就为true | [ 1 -gt 1 -o 2 -eq 2 ] |
! |
结果取反 | |
结果取反
[root@yuchaoit666 ~]#[ 1 -eq 1 ] && echo true || echo false
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ ! 1 -eq 1 ] && echo true || echo false
false
或运算
[root@yuchaoit666 ~]#[ 1 -eq 1 -o 2 -gt 2 ] && echo yes || echo no
yes
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -gt 2 ] && echo yes || echo no
no
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -lt 2 ] && echo yes || echo no
no
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -eq 2 ] && echo yes || echo no
yes
并且运算
[root@yuchaoit666 ~]#[ 6 -eq 6 -a 8 -gt 3 ] && echo true || echo no
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 6 -eq 6 -a 8 -lt 3 ] && echo true || echo no
no