Linux云计算 |【第二阶段】SHELL-DAY2

主要内容:

条件测试(字符串比较、整数比较、文件状态)、IF选择结构(单分支、双分支、多分支)、For循环结构、While循环结构

一、表达式比较评估

test 命令是 Unix 和 Linux 系统中用于评估条件表达式的命令。它通常用于 shell 脚本中,以根据条件执行不同的操作。test 命令可以检查文件类型、比较字符串和整数,以及执行逻辑操作。

可以为Shell脚本实现智能化判断的结果,为命令的执行提供最直接的识别依据;针对文件或目录的读/写等状态、数值的大小、字符串是否匹配、多条件组合;

  • 格式:test expression
  • 格式:[ expression ]

或者使用方括号 [ ](注意方括号与表达式之间要有空格)

注意:条件测试操作本身不显示出任何信息。测试的条件是否成立主要体现在命令执行后的返回状态(即 $?),所以可以在测试后查看变量$?的值来做出判断,或者结合&&、||等逻辑操作显示出结果(或作其他操作)

文件测试

  • -e file:检查文件是否存在。
  • -f file:检查文件是否存在且为普通文件。
  • -d file:检查文件是否存在且为目录。
  • -r file:检查文件是否存在且可读。
  • -w file:检查文件是否存在且可写。
  • -x file:检查文件是否存在且可执行。
  • -s file:检查文件是否存在且大小大于0。

字符串比较

  • str1 = str2:检查字符串是否相等。
  • str1 != str2:检查字符串是否不相等。
  • -z str:检查字符串是否为空。
  • -n str:检查字符串是否非空。

整数比较

  • int1 -eq int2:检查整数是否相等。
  • int1 -ne int2:检查整数是否不相等。
  • int1 -lt int2:检查整数是否小于。
  • int1 -le int2:检查整数是否小于等于。
  • int1 -gt int2:检查整数是否大于。
  • int1 -ge int2:检查整数是否大于等于。

逻辑操作

  • ! expression:逻辑非。
  • expression1 -a expression2:逻辑与(AND)。
  • expression1 -o expression2:逻辑或(OR)。

二、常用表达式

1、字符串比较测试

格式:[ 操作符 字符串 ]      //查看变量的值是否为空

  • -z str:检查字符串是否为空
  • -n str:检查字符串是否非空

注意:格式必须要有空格 

例如:

[root@svr7 ~]# a=100
[root@svr7 ~]# [ -z $a ]     //判断变量a为空
[root@svr7 ~]# echo $?
1
可以简化为如下形式:
[root@svr7 ~]# a=100;[ -z $a ];echo $?    //利用【;】号可隔开表达式
1[root@svr7 ~]# [ ! -z $a ]    //判断变量a不为空
[root@svr7 ~]# echo $?
0
[root@svr7 ~]# [ -n $a ]     //判断变量a不为空
[root@svr7 ~]# echo $?
0

 例如:

[root@svr5 ~]# var1="nb" ; var2=""
[root@svr5 ~]# [ -z "$var1" ] && echo "空值" || echo "非空值"    //-z查看字符串值为空
非空值
[root@svr5 ~]# [ -z $var2 ] && echo "空值" || echo "非空值"
空值               //变量var2已设置,但无任何值,视为空

常见报错:【! -z】在!与 -z间需要加空格

[root@svr7 ~]# [ !-z $a ]
-bash: !-z: event not found

格式:[ 字符串1 操作符 字符串2 ]    //查看变量的值是否相同

  • str1 == str2:检查字符串是否相等
  • str1 != str2:检查字符串是否不相等

注意:格式必须要有空格

例如:

[root@svr7 ~]# [ abc == abc ]     //字符串的值测试是否相同(常量)
[root@svr7 ~]# echo $?     //判断上条命令是否正确(0正确,非0错误)
0
[root@svr7 ~]# [ “root” == $USER ]     //当前用户是否与root相同(变量)
[root@svr7 ~]# echo $?
0
[root@svr7 ~]# [ “root” != $USER ]    //当前用户是否与root不同
[root@svr7 ~]# echo $?
1

常见报错:输入格式错误,未有空格

[root@svr7 ~]# [abc == abc]
bash: [abc: 未找到命令...

2、整数值比较测试

格式:[ 整数值1 操作符 整数值2 ]

  • int1 -eq int2:检查整数是否相等
  • int1 -ne int2:检查整数是否不相等
  • int1 -lt int2:检查整数是否小于
  • int1 -le int2:检查整数是否小于等于
  • int1 -gt int2:检查整数是否大于
  • int1 -ge int2:检查整数是否大于等于

例如:

[root@svr7 opt]# a=10
[root@svr7 opt]# [ $a -eq 9 ];echo $?    //测试10等于9,报错
1
[root@svr7 opt]# [ $a -eq 10 ];echo $?   //测试10等于10
0
[root@svr7 opt]# [ $a -ne 9 ];echo $?     //测试10不等于9
0
[root@svr7 opt]# [ $a -ge 7 ];echo $?      //测试10大于或等于7
0
[root@svr7 opt]# [ $a -le 7 ];echo $?     //测试10小于或等于7
1
[root@svr7 opt]# [ $a -gt 4 ];echo $?    //测试10大于4
0
[root@svr7 opt]# [ $a -lt 4 ];echo $?    //测试10小于4
1

例如:

[root@svr5 ~]# X=20    //定义一个测试变量
[root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等"
相等
[root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等"
不相等[root@svr5 ~]# [ $X -gt 10 ] && echo "大于" || echo "否"
大于
[root@svr5 ~]# [ $X -gt 20 ] && echo "大于" || echo "否"
否
[root@svr5 ~]# [ $X -gt 30 ] && echo "大于" || echo "否"
否[root@svr5 ~]# [ $X -ge 10 ] && echo "大于或等于" || echo "否"
大于或等于
[root@svr5 ~]# [ $X -ge 20 ] && echo "大于或等于" || echo "否"
大于或等于
[root@svr5 ~]# [ $X -ge 30 ] && echo "大于或等于" || echo "否"
否

例如:提取当前登录的用户数,比较是否大于等于3

[root@svr5 ~]# who | wc -l         //确认已登录的用户数
2
[root@svr5 ~]# N=$(who | wc -l)        //赋值给变量N
[root@svr5 ~]# [ $N -ge 3 ] && echo "超过了" || echo "没超过"
没超过## 上述赋值给变量N及与3比较的操作,可以简化为如下形式:
[root@svr5 ~]# [ $(who | wc -l) -ge 3 ] && echo "超过了" || echo "没超过"
没超过

常见报错:参与比较的必须是整数(可以调用变量),比较非整数值时会出错:

[root@svr5 ~]# A=20.4
[root@svr5 ~]# [ $A -gt 10 ]     //不支持小数比较
-bash: [: 20.4: integer expression expected

3、文件比较测试

格式:[ 操作符 文件或目录 ]

  • -e file:检查文件是否存在
  • -f file:检查文件是否存在且为普通文件
  • -d file:检查文件是否存在且为目录
  • -r file:检查文件是否存在且可读
  • -w file:检查文件是否存在且可写
  • -x file:检查文件是否存在且可执行
  • -s file:检查文件是否存在且大小大于0

补充:-e 判断文件不关心类型、-f判断文件必须是普通文件、-d判断文件必须是目录

例如:-e 判断对象是否存在(不管是目录还是文件)

[root@svr5 ~]# [ -e "/usr/" ] && echo "存在" || echo "不存在"
存在
[root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在"
存在
[root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在"
不存在

例如:-d 判断对象是否为目录(存在且是目录)

[root@svr5 ~]# [ -d "/usr/" ] && echo "是目录" || echo "不是目录"
是目录
[root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目录" || echo "不是目录"
不是目录
[root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目录" || echo "不是目录"
不是目录 

例如:-f 判断对象是否为文件(存在且是文件)

[root@svr5 ~]# [ -f "/usr/" ] && echo "是文件" || echo "不是文件"
不是文件
[root@svr5 ~]# [ -f "/etc/fstab" ] && echo "是文件" || echo "不是文件"
是文件
[root@svr5 ~]# [ -f "/home/nooby" ] && echo "是文件" || echo "不是文件"
不是文件

例如:-r 判断对象是否可读

此测试对root用户无效,无论文件是否设置r权限,root都可读;

[root@svr5 ~]# cp /etc/hosts /tmp/test.txt          //复制一个文件做测试
[root@svr5 ~]# chmod -r /tmp/test.txt              //去掉所有的r权限
[root@svr5 ~]# [ -r "/tmp/test.txt" ] && echo "可读" || echo "不可读"
可读                                              //root测试结果仍然可读# 切换为普通用户,再执行相同的测试,结果变为“不可读”:
[lisi@svr5 ~]$ [ -r "/tmp/test.txt" ] && echo "可读" || echo "不可读"
不可读

例如:-w 判断对象是否可写

此测试同样对root用户无效,无论文件是否设置w权限,root都可写;

[root@svr5 ~]# chmod -w /tmp/test.txt             //去掉所有的w权限
[root@svr5 ~]# ls -l /tmp/test.txt              //确认设置结果
---------- 1 root root 33139 12-11 10:43 /tmp/test.txt
[root@svr5 ~]# [ -w "/tmp/test.txt" ] && echo "可写" || echo "不可写"
可写# 切换为普通用户,可以正常使用-w测试:
[lisi@svr5 ~]$ ls -l /tmp/test.txt
---------- 1 root root 33139 12-11 10:52 /tmp/test.txt
[lisi@svr5 ~]$ [ -w "/tmp/test.txt" ] && echo "可写" || echo "不可写"
不可写

例如:-x 判断对象是否具有可执行权限

这个取决于文件本身、文件系统级的控制,root或普通用户都适用:

[root@svr5 ~]# chmod 644 /tmp/test.txt          //重设权限,无x
[root@svr5 ~]# ls -l /tmp/test.txt              //确认设置结果
-rw-r--r-- 1 root root 33139 12-11 10:52 /tmp/test.txt
[root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可执行" || echo "不可执行"
不可执行
[root@svr5 ~]# chmod +x /tmp/test.txt          //添加x权限
[root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可执行" || echo "不可执行"
可执行

4、逻辑分隔操作

格式:命令1 操作符 命令2...

格式:[ 条件1 ] 操作符 [ 条件2 ]...

  • A && B      //仅当A命令执行成功,才执行B命令
  • A || B       //仅当A命令执行失败,才执行B命令
  • A ; B      //执行A命令后执行B命令,两者没有逻辑关系

&&,逻辑与  前面条件成立且后条件也成立,则整个测试结果就为真,就会执行之后的指令;

||,逻辑或   前面条件失败才执行之后的指令,且两条件其中某一条件成立,则测试结果就算为真;

补充:

格式:! expression:逻辑非

格式:expression1 -a expression2:逻辑与(AND)

格式:expression1 -o expression2:逻辑或(OR)

例如:

[root@svr7 ~]# [ a == a ] && echo ab   //&&条件都成立,指令执行
ab
[root@svr7 ~]# [ a == b ] && echo ab    //&&其中条件不成立,指令不执行
[root@svr7 ~]# [ a == b ] || echo ab   //||只要遇到条件成立,指令执行;
ab

例如:

[root@svr7 ~]# touch a b c     //创建文件a b c
[root@svr7 ~]# ls a && ls b && ls c
a
b
c

解释:第一个&&条件都成立(为真)并全部执行;第二个&&以第一个&&作为条件判断,条件都成立(为真)并执行。最终输出:a b c

[root@svr7 ~]# ls a || ls b && ls c
a
c

解释:||条件ls a成立(为真)直接执行,忽略ls b;&&以||结果作为条件判断,条件都成立(为真)并执行,最终输出:a c

[root@svr7 ~]# ls a && ls b || ls c
a
b

解释:&&条件都成立(为真)并全部执行,||以&&结果作为条件判断,条件成立(为真)已执行,忽略ls c。最终输出:a b

[root@svr7 ~]# ls a || ls b || ls c
a

解释;第一个||条件ls a成立(为真)并执行,忽略ls b;第二个||以第一个||作为条件判断,条件成立且已执行ls a,忽略ls b和ls c。最终输出:a

[root@svr7 ~]# ls d || ls b && ls c
ls: 无法访问d: 没有那个文件或目录
b
c

解释:||条件ls d不成立,条件ls b成立(为真)并执行,&&以第一个||作为条件判断,条件成立并执行,最终输出:b c

例如:检查变量X的值是否大于10,且小于30:

[root@svr5 ~]# X=20      //设置X变量的值为20
[root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
YES

例如:只要/tmp/、/var/spool/目录中有一个可写,则条件成立:(/tmp临时文件,权限0)

[root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
OK

案例1:判断用户名是否为管理员,若判断输入值非root,则输出报错信息并退出脚本

[root@svr7 opt]# vim /opt/test05.sh
#!/bin/bash
[ root != $USER ] && echo "报错:非管理员用户" && exit    //判断用户非root,报错并退出
yum -y install vsftpd     //安装ftp服务
systemctl restart vsftpd
systemctl enable vsftpd[root@svr7 ~]# su - ABC    //登录其它用户测试
[ABC@svr7 ~]$ bash /opt/test05.sh
报错:非管理员用户

案例2:判断用户名是否为空,若输入值为空,则输出报错信息并退出脚本

[root@svr7 opt]# vim /opt/test08.sh
#!/bin/bash
read -p "请输入账号:" user    //定义变量user,用户名
[ -z $user ] && echo "报错:输入账号为空" && exit    //判断用户名为空,报错并退出
useradd $user    //创建用户
stty -echo
read -p "请输入密码:" pass    //定义变量pass,密码
stty echo
echo $pass | passwd --stdin $user    //配置密码

案例3:判断用户的UID是否为0(UID:0为root),当用户的ID不等于0就退出

[root@svr7 ~]# vim /opt/test04.sh
#!/bin/bash
[ 0 -ne $UID ] && exit      //用户的ID不等于0就退出
yum -y install httpd &> /dev/null    //安装httpd服务
echo "WEB HELLO" > /var/www/html/index.html
systemctl restart httpd
systemctl enable httpd &> /dev/null

案例4:编写脚本,每2分钟检测服务器是否新增软件包,发现新增则给管理员发邮件

[root@svr7 opt]# vim mail-test.sh
#!/bin/bash
x=$(rpm -qa | wc -l)    //定义变量:rpm -qa | wc -l的输出结果
[ $x -gt 1307 ] && echo "服务器软件包超出预定值,请排查!" | mail -s test root    //数值比较,1307为新增软件包前的数量值
[root@svr7 opt]# chmod u+x mail-test.sh     //赋予执行权限— 编辑周期性计划任务:
[root@svr7 opt]# crontab -e
crontab: installing new crontab
[root@svr7 opt]# crontab -l
*/2 * * * * /opt/mail-test.sh    //每2分钟运行脚本— 测试:
[root@svr7 opt]# mail
Heirloom Mail version 12.5 7/5/10.  Type ? for help.
"/var/spool/mail/root": 4 messages 4 new
>N  4 root                  Fri Apr  2 16:28  18/581   "test"
& 4      
Message  4:
From root@svr7.tedu.cn  Fri Apr  2 16:28:02 2021
Return-Path: <root@svr7.tedu.cn>
X-Original-To: root
Delivered-To: root@svr7.tedu.cn
Date: Fri, 02 Apr 2021 16:28:02 +0800
To: root@svr7.tedu.cn
Subject: test
User-Agent: Heirloom mailx 12.5 7/5/10
Content-Type: text/plain; charset=utf-8
From: root@svr7.tedu.cn (root)
Status: R服务器软件包超出预定值,请排查!

  

三、IF选择结构

在 shell 脚本中,if 语句用于根据条件执行不同的操作。if 语句可以分为单分支、双分支和多分支结构。下面分别介绍这三种结构及其示例。

1、单分支结构

特点:当“条件成立”时,执行命令序列,否则不执行任何操作;

if单分支的执行流程

  • 语法格式:
if condition; then# commands to execute if condition is true
fi

示例:

#!/bin/bash
if [ 0 -eq $UID ] ;thenecho "您好,您是管理员"
fi
#!/bin/bash
if [ -e /path/to/file ]; thenecho "File exists"
fi

2、双分支结构

特点:当“条件成立”时,执行命令序列1,否则执行命令序列2;

if双分支的执行流程

  • 语法格式:
if condition; then# commands to execute if condition is true
else# commands to execute if condition is false
fi

示例:

#!/bin/bash
if [ 0 -eq $UID ] ;thenecho "您好,您是管理员"
elseecho "您好,您不是管理员"
fi
#!/bin/bash
if [ -e /path/to/file ]; thenecho "File exists"
elseecho "File does not exist"
fi

案例:利用双分支编写Ping测试脚本

任务需求:使用ping命令检测目标主机时,人工可直接判断反馈结果,而脚本却不方便。但是当ping测试成功时,执行状态$?的值为0;而ping测试失败时,$?的值不为0。因此在Shell脚本中可以利用这一点来判断ping目标主机的成败;

补充:

  • [-c]  指定ping包次数;
  • [-i]   定义ping包间隔时间(缩短发送测试包的间隔秒数)
  • [-W]  ping测试IP若不成功,直接反馈(等待反馈的超时秒数)

步骤1:

[root@svr7 opt]# ping -c 3 -i 0.2 -W 1 192.168.4.7
PING 192.168.4.7 (192.168.4.7) 56(84) bytes of data.
64 bytes from 192.168.4.7: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from 192.168.4.7: icmp_seq=2 ttl=64 time=0.032 ms
64 bytes from 192.168.4.7: icmp_seq=3 ttl=64 time=0.035 ms
--- 192.168.4.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 399ms
rtt min/avg/max/mdev = 0.030/0.032/0.035/0.005 ms
[root@svr7 opt]# echo $?
0[root@svr7 opt]# ping -c 3 -i 0.2 -W 1 192.168.4.78      //不存在IP
PING 192.168.4.78 (192.168.4.78) 56(84) bytes of data.
--- 192.168.4.78 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 419ms
[root@svr7 opt]# echo $?
1

步骤2:检测单台主机的存活状态

[root@svr7 opt]# vim test03.sh     //编写脚本
#!/bin/bash
ping -c 3 -i 0.2 -W 1 192.168.4.7 > /dev/null
if [ $? -eq 0 ] ;thenecho "Ping通了"
elseecho "Ping没通"
fi    
[root@svr7 opt]# bash test03.sh
Ping通了[root@svr7 opt]# vim test03.sh     //编写脚本
ping -c 3 -i 0.2 -W 1 192.168.4.78 > /dev/null      //不存在的IP
...
[root@svr7 opt]# bash test03.sh
Ping没通

3、多分支结构

特点:相当于if语句嵌套,针对多个条件分别执行不同的操作;

if多分支的执行流程

  • 语法格式:
if condition1; then# commands to execute if condition1 is true
elif condition2; then# commands to execute if condition2 is true
else# commands to execute if no condition is true
fi

示例:

score=85   ##定义变量if [ "$score" -ge 90 ]; thenecho "Grade: A"
elif [ "$score" -ge 80 ]; thenecho "Grade: B"
elif [ "$score" -ge 70 ]; thenecho "Grade: C"
elseecho "Grade: D"
fi

案例:通过if多分支实现分数判断

[root@svr7 opt]# vim test04.sh
#!/bin/bash
read -p "本次月考成绩如何?" num
if [ $num -ge 90 ] ;thenecho "$num分,优秀!"
elif [ $num -ge 80 ] ;thenecho "$num分,良好!"
elif [ $num -ge 60 ] ;thenecho "$num分,及格!"
elseecho "$num分,继续努力"
fi

总结

if 语句在 shell 脚本中用于根据条件执行不同的操作。通过掌握单分支、双分支和多分支结构,可以编写更灵活和功能强大的脚本。结合 test 命令,可以评估各种条件表达式,进一步增强脚本的功能和实用性。

四、循环结构

在 shell 脚本中,for 循环和 while 循环是两种常用的循环结构,用于重复执行一组命令。下面分别介绍这两种循环结构及其示例。

1、For循环

特点:采用遍历式、列表式的执行流程,通过指定变量从值列表中循环赋值,每次复制后执行固定的一组操作(根据变量的不同取值,有次数的重复执行命令序列)

for循环的执行流程

  • 语法格式1:
for variable in list; do# commands to execute for each element in the list
done

示例:遍历数字范围

#!/bin/bash
for i in {1..5}; doecho "Number: $i"
done

示例:遍历数组

#!/bin/bash
fruits=("apple" "banana" "cherry")for fruit in "${fruits[@]}"; doecho "Fruit: $fruit"
done

示例:遍历文件列表

#!/bin/bash
for file in /path/to/directory/*; doif [ -f "$file" ]; thenecho "File: $file"fi
done

例如:通过循环批量显示3个haha

[root@svr7 opt]# vim test01.sh
#!/bin/bash
for i in a b c
doecho hahaecho $i
done# 测试:
[root@svr7 opt]# bash test01.sh
haha
a
haha
b
haha
c

例如:通过循环批量显示5个haha

[root@svr7 opt]# vim test01.sh
#!/bin/bash
for i in {1..5}
doecho hahaecho $i
done# 测试:
[root@svr7 opt]# bash test01.sh
haha
1
haha
2
haha
3
haha
4
haha
5

例如:批量检测多个主机的存活状态

[root@svr7 opt]# vim test02.sh
#!/bin/bash
for i in {205..210}
doping -c 3 -i 0.2 -w 1 192.168.4.$i &> /dev/nullif [ $? -eq 0 ];thenecho "ping 192.168.4.$i,通了"elseecho "ping 192.168.4.$i,没通"fi
done# 测试:
[root@svr7 opt]# bash test02.sh
ping 192.168.4.205,没通
ping 192.168.4.206,没通
ping 192.168.4.207,通了
ping 192.168.4.208,没通
ping 192.168.4.209,没通
ping 192.168.4.210,没通

例如:批量检测多个主机的存活状态(优化)

[root@svr7 opt]# vim test02.sh
#!/bin/bash
x=0
y=0
for i in {205..210}
doping -c 3 -i 0.2 -w 1 192.168.4.$i &> /dev/nullif [ $? -eq 0 ];thenecho "ping 192.168.4.$i,通了"let x++elseecho "ping 192.168.4.$i,没通"let y++fi
done
echo "$x台通了,$y台不通"# 测试:
[root@svr7 opt]# bash test02.sh
ping 192.168.4.205,没通
ping 192.168.4.206,没通
ping 192.168.4.207,通了
ping 192.168.4.208,没通
ping 192.168.4.209,没通
ping 192.168.4.210,没通
1台通了,5台不通

案例:创建users.txt,写入无规律的账户名称,使用for循环读取该文件,批量创建账户并设置密码;

[root@svr5 ~]# vim addfor.sh
#!/bin/bash
for i in `cat /root/user.txt`
douseradd $iecho 123456 | passwd --stdin $i
done

附加扩展知识(C语言风格的for循环语法格式)

2、While循环

特点:while循环属于条件式的执行流程,会反复判断指定的测试条件,只要条件成立即执行固定的一组操作,直到条件变化为不成立为终止。所以while循环的条件一般通过变量来进行控制,在循环体内对变量值做相应改变,以便在适当的时候退出,避免陷入死循环,(条件式循环,反复测试条件,只要成立就执行命令序列,不成立终止)

 while循环的执行流程

  • 语法格式1:
while condition; do# commands to execute while condition is true
done
  • 语法格式2:  //【:】条件永远成立,死循环
while : do# commands to execute while condition is true
done

示例:基本用法

counter=1while [ $counter -le 5 ]; doecho "Counter: $counter"counter=$((counter + 1))
done

示例:读取文件内容

while read -r line; doecho "Line: $line"
done < /path/to/file

示例:无限循环

while true; doecho "This is an infinite loop. Press Ctrl+C to exit."sleep 1
done

示例:结合 if 语句使用

for file in /path/to/directory/*; doif [ -f "$file" ]; thenecho "File: $file"elif [ -d "$file" ]; thenecho "Directory: $file"fi
done

例如:

[root@svr7 opt]# vim while01.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
doecho "$i"let i++        //不加自增,则为死循环,需要使用Ctrl+C终止脚本
done
[root@svr7 opt]# bash while01.sh

例如:

[root@svr7 opt]# vim while02.sh
#!/bin/bash
while :      //【:】条件永远成立
doecho "hello world"
done
[root@svr7 opt]# bash while02.sh       //死循环,需要使用Ctrl+C终止脚本


案例1:使用系统自带变量RANDOM提取随机数(1-100),使用while :制作死循环

[root@svr5 ~]# vim guess.sh
#!/bin/bash
num=$[RANDOM%100+1]
i=0
while :
doread -p "随机数1-100,你猜:" guesslet i++                                 //猜一次,计数器加1,统计猜的次数if [ $guess -eq $num ];thenecho "恭喜,猜对了"echo "你猜了$i次"exitelif [ $guess -gt $num ];thenecho "猜大了"elseecho "猜小了"fi
done[root@svr5 ~]# chmod +x guess.sh
[root@svr5 ~]# ./guess.sh

案例2:检测192.168.4.0/24网段,列出不在线的主机地址

检测目标是一个网段,其网络部分“192.168.4.”可以作为固定的前缀;而主机部分包括从1~254连续的地址,所以可结合while循环和自增变量进行控制。

[root@svr5 ~]# vim chknet.sh
#!/bin/bash
i=1
while [ $i -le 254 ]
doIP="192.168.4.$i"ping -c 3 -i 0.2 -W 1 $IP &> /dev/nullif [ $? -eq 0 ] ; thenecho "Host $IP is up."elseecho "Host $IP is down."filet i++
done[root@svr5 ~]# chmod +x chknet.sh#测试:
[root@svr5 ~]# ./chknet.sh
Host 192.168.4.1 is down.
Host 192.168.4.2 is down.
Host 192.168.4.3 is down.
Host 192.168.4.4 is down.
Host 192.168.4.5 is up.
.. ..
Host 192.168.4.250 is down.
Host 192.168.4.251 is down.
Host 192.168.4.252 is down.
Host 192.168.4.253 is down.
Host 192.168.4.254 is down.

补充:sleep 0.2   //如果系统执行任务消耗cpu比较多,可以每次稍微休息0.2秒


常见报错:判断的测试条件左右未加空格;

[root@svr7 opt]# [1 -gt 2]
bash: [1: 未找到命令...
[root@svr7 opt]# [1-gt2]
bash: [1-gt2]: 未找到命令...

常见报错:if语句开始,需要配合使用fi作为判断结束符号;

[root@svr7 opt]# vim test.sh
#!/bin/bash
if [ a = a ];thenecho a
[root@svr7 opt]# bash test.sh
test.sh:行4: 语法错误: 未预期的文件结尾

常见报错:无法对空值进行判断

[root@svr7 opt]# vim test.sh
#!/bin/bash
if [ $a -eq 2 ];thenecho a
fi
[root@svr7 opt]# bash test.sh
test.sh: 第 2 行:[: -eq: 期待一元表达式
报错信息:[: -eq: unary operator expected]

附加扩展知识(C语言风格的for循环语法格式:for ((初值;条件;步长控制)))

[root@svr7 opt]# vim test.sh
#!/bin/bash
for ((i=1;i<=5;i+=2))
doecho $i
done
[root@svr7 opt]# bash test.sh
1
3
5

常见报错:基本语法错误,for ((初值;条件;步长控制))

[root@svr7 opt]# vim test.sh
#!/bin/bash
for (i=1;i<=5;i+=2)
doecho $i
done
[root@svr7 opt]# bash test.sh
test.sh:行2: 未预期的符号 `(' 附近有语法错误
test.sh:行2: `for (i=1;i<=5;i+=2)'

常见报错:for循环的执行体,需要嵌入到do和done中间

[root@svr7 opt]# vim test.sh
#!/bin/bash
for i in 1 2echo $i
[root@svr7 opt]# bash test.sh
test.sh:行3: 未预期的符号 `echo' 附近有语法错误
test.sh:行3: `  echo $i'

总结

for 循环和 while 循环是 shell 脚本中非常有用的工具,用于重复执行一组命令。通过掌握这两种循环结构,可以编写更灵活和功能强大的脚本。结合 if 语句,可以进一步增强脚本的功能和实用性。

小结:

本篇章节为【第二阶段】SHELL-DAY2 的学习笔记,这篇笔记可以初步了解到条件测试(字符串比较、整数比较、文件状态)、IF选择结构(单分支、双分支、多分支)、For循环结构、While循环结构。


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/409839.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

致远OA OCR票据识别组件

OCR票据识别 技术支持 技术大佬支持本文档 使用范围 任何票种信息&#xff0c;只要需要对接到oa底表中&#xff0c;就能够实现各种票种&#xff0c;各种字段的对接&#xff0c;包括票据识别&#xff0c;发票核验&#xff0c;适配各种票据 使用介绍 1 配置每种发票的ocr设…

yup 使用 2 - 获取默认值,循环依赖,超大数字验证,本地化

yup 使用 2 - 获取默认值&#xff0c;循环依赖&#xff0c;超大数字验证&#xff0c;本地化 上一篇的使用在这里&#xff1a;yup 基础使用以及 jest 测试&#xff0c;这篇讲的是比较基础的东西&#xff0c; 获取默认值 之前用的都是 cast({})&#xff0c;然后如果有些值是必…

叉车(工业车辆)安全管理系统,云端监管人车信息运营情况方案

近年来&#xff0c;国家和各地政府相继出台了多项政策法规&#xff0c;从政策层面推行叉车智慧监管&#xff0c;加大叉车安全监管力度。同时鼓励各地结合实际&#xff0c;积极探索智慧叉车建设&#xff0c;实现作业人员资格认证、车辆状态认证、安全操作提醒、行驶轨迹监控等&a…

如何利用电商 API 数据分析助力精准选品!

电商 API 数据分析在选品过程中起着至关重要的作用&#xff0c;它们之间有着密切的关系&#xff1a; 一、提供市场趋势洞察 热门商品识别&#xff1a; 通过分析电商 API 中的销售数据&#xff0c;包括商品的销售量、销售额、销售频率等指标&#xff0c;可以快速准确地识别出当…

1Panel应用推荐:MeterSphere开源持续测试工具

1Panel&#xff08;github.com/1Panel-dev/1Panel&#xff09;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;它致力于通过开源的方式&#xff0c;帮助用户简化建站与运维管理流程。为了方便广大用户快捷安装部署相关软件应用&#xff0c;1Panel特别开通应用商店&am…

redis面试(二十一)读写锁互斥

读锁非互斥 非互斥的意思就是&#xff0c;一个客户端或者线程加锁之后&#xff0c;另一个客户端线程也可以来进行加锁。 还是拿着ReadLock的lua脚本来看看 刚才我们已经分析过第一个线程来加读锁的逻辑了 所以上半截不用重复说了&#xff0c; hset anyLock mode read hset an…

后端微服务架构:构建分布式博客系统

后端微服务架构&#xff1a;构建分布式博客系统 在当今的软件开发领域&#xff0c;微服务架构已经成为构建可扩展、灵活且易于维护的应用程序的主流选择。本文将探讨如何利用微服务架构来设计和实现一个分布式的博客系统。 1. 微服务架构简介 微服务架构是一种将应用程序分解…

【微服务部署】Linux部署微服务启动报ORA-01005

问题背景&#xff1a; Linux机器部署springboot微服务&#xff0c;部署完成后发现无法启动&#xff0c;后台报ORA-01005错误。 解决方案&#xff1a; 1.检查当前服务器是否已安装oracle客户端 命令行执行sqlplus username/passwd实例名&#xff0c;如果执行成功&#xff0c;说…

微信小程序源码 图书管理系统 万字文档 Springboot vue

源码地址 系统演示 SpringBoot vue 微信小程序源码 图书管理系统 附带运行教程 系统演示 万字文档&#xff0c;全套开发工具 开发工具:IDEA,微信小程序工具 数据库:mysql8 使用环境:Windows JDK版本:1.8 后端构建工具:maven 项目使用到的技术栈 Springboot2 mybatis vue Mys…

计算机毕业设计选题推荐-摇滚音乐鉴赏网站-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

领域驱动设计DDD详解与战术建模落地

一、什么是DDD&#xff1f; 1.1、DDD的概念 Domain-Driven Design&#xff08;领域驱动设计&#xff09;它由Eric Evans在他的2003年出版的书籍《Domain-Driven Design: Tackling Complexity in the Heart of Software》中首次提出。DDD 核心思想是通过领域驱动设计方法定义领…

透明度测试

&#xff11;、透明测试是用于处理哪种透明需求 在游戏开发中对象的某些部位完全透明而其他部位完全不透明,这种透明需求往往不需要半透明效果,相对比较极端&#xff0c;只有看得见和看不见之分比如树叶、草、栅栏等等。&#xff08;即一张图除了主要物体有颜色&#xff0c;其…

奇文网盘项目对应windows版本的中间件下载,otp,rabbitmq,postgresql,onlyoffice(在线预览编辑等)

之前的解压是百度网盘&#xff0c;要会员&#xff0c;油猴也无法下载&#xff0c;所有我下载之后给你们提供阿里云盘链接&#xff08;不限速&#xff09; 本次软件版本介绍&#xff1a; 01-otp_win64_24.1 02-rabbitmq-server-3.9.8 03-postgresql-9.6.23-2-windows-x64 0…

如何解决错误Given calling package android does not match caller‘s uid-学员提问

背景&#xff1a; 近来有学员反馈说wms课程中讲解的借壳Shell帮忙执行一些shell命令有问题&#xff0c;具体啥问题呢&#xff1f; 在ShellProvider的call方法加入如下代码&#xff1a; 目的就是想让shell帮我们执行一下settings值的写入&#xff0c;这里其实可以更加简单的set…

Linux 定时备份

背景&#xff1a;为防止数据丢失&#xff0c;要求每天备份一次 以达梦数据库为例&#xff0c;每天定时备份 1.填写备份脚本 vi db_day_backup.sh #!/bin/bash DIR$(cd $(dirname $0) && pwd) tarnamedata.tar_$(date %Y%m%d) cd $DIR if [[ $(find $DIR/ -name $tar…

腾讯提出一种新的针对风格化角色和逼真服装动画的生成3D运动转移方法,生成效果逼真!

来自腾讯XR视觉实验室的研究团队提出了一种创新的3D运动转移方法&#xff0c;专门针对风格化角色和逼真服装动画的生成。该方法能够将源动作准确地映射到目标角色上&#xff0c;同时考虑了角色身体的刚性变形和服装的局部物理动态变形。 与现有技术相比&#xff0c;这技术不仅…

4、Unity【基础】画线功能Linerenderer、物理系统Physics

文章目录 画线功能Linerenderer1、LineRenderer是什么2、LineRender参数相关3、LineRender代码相关思考1 请写一个方法&#xff0c;传入一个中心点&#xff0c;传入一个半径&#xff0c;用LineRender画个圆出来思考2 在Game窗口长按鼠标用LineRender画出鼠标移动的轨迹 核心系统…

Axure设计之单选框教程(中继器)

在Axure RP中&#xff0c;通过结合中继器的强大功能&#xff0c;我们可以轻松实现动态加载的单选框列表&#xff0c;不仅可以根据数据自动调整选项宽度&#xff0c;还能实时更新选中状态。本教程将引导你完成一个使用中继器制作动态单选框列表的项目&#xff0c;包括案例分析、…

Linux文件IO缓存

一、缓冲区大小对 I/O 系统调用性能的影响 总之&#xff0c;如果与文件发生大量的数据传输&#xff0c;通过采用大块空间缓冲数据&#xff0c;以及执行更少的 系统调用&#xff0c;可以极大地提高 I / O 性能 二、stdio 库的缓冲 当操作磁盘文件时&#xff0c;缓冲大块数据以…

树数据结构(Tree Data Structures)的全面指南:深度解析、算法实战与应用案例

树数据结构&#xff08;Tree Data Structures&#xff09;的全面指南&#xff1a;深度解析、算法实战与应用案例 引言 树数据结构&#xff08;Tree Data Structures&#xff09;作为计算机科学中的基石之一&#xff0c;以其独特的层次结构和分支特性&#xff0c;在众多领域发…