shell/流程控制.md

551 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h1><center>流程控制</center></h1>
------
## 一:条件测试
#### 1.语法格式
```shell
格式1 test 条件表达式
格式2 [ 条件表达式 ]
格式3 [[ 条件表达式 ]]
```
#### 2.文件测试
```shell
[ -e dir|file ]
[ -d dir ]
[ -f file ] 是否存在,而且是文件
[ -r file ] 当前用户对该文件是否有读权限
[ -x file ]
[ -w file ]
```
案例
```shell
[root@xingdian ~]# test -d /home
[root@xingdian ~]# echo $?
0
[root@xingdian ~]# test -d /home11111
[root@xingdian ~]# echo $?
1
[root@xingdian ~]# [ -d /home ]
[root@xingdian ~]# [ ! -d /ccc ] && mkdir /ccc
[root@xingdian ~]# [ -d /ccc ] || mkdir /ccc
```
#### 3.数值比较
```shell
[ 1 -gt 10 ] 大于
[ 1 -lt 10 ] 小于
[ 1 -eq 10 ] 等于
[ 1 -ne 10 ] 不等于
[ 1 -ge 10 ] 大于等于
[ 1 -le 10 ] 小于等于
```
案例
```shell
[root@xingdian ~]# disk_use=$(df -P |grep '/$' |awk '{print $5}' |awk -F% '{print $1}')
[root@xingdian ~]# [ $disk_use -gt 90 ] && echo "war......"
[root@xingdian ~]# [ $disk_use -gt 60 ] && echo "war......"
```
```shell
[root@xingdian ~]# [ $(id -u) -eq 0 ] && echo "当前是超级用户"
当前是超级用户
[alice@xingdian ~]$ [ $UID -eq 0 ] && echo "当前是超级用户" || echo "you不是超级用户"
you不是超级用户
```
#### 4.字符串比较
```shell
提示:使用双引号
[root@xingdian ~]# [ "$USER" = "root" ];echo $?
0
[root@xingdian ~]# [ "$USER" == "root" ];echo $?
0
```
注意:
```shell
"":弱引用,可以实现变量和命令的替换
[root@xingdian ~]# x=*
[root@xingdian ~]# echo "$x"
*
'':强引用,不完成变量替换
[root@xingdian ~]# x=*
[root@xingdian ~]# echo '$x'
$x
```
#### 5.扩展
```shell
[root@xingdian ~]# var1=111
[root@xingdian ~]# var2=
[root@xingdian ~]# //var3变量没有定义
[root@xingdian ~]# echo ${#var1} #显示变量中字符串的个数
3
[root@xingdian ~]# echo ${#var2}
0
[root@xingdian ~]# echo ${#var3}
0
[root@xingdian ~]# [ -z "$var1" ];echo $? //-z 变量字符串为空
1
[root@xingdian ~]# [ -z "$var2" ];echo $?
0
[root@xingdian ~]# [ -z "$var3" ];echo $?
0
[root@xingdian ~]# [ -n "$var1" ];echo $? //-n 变量字符串不为空
0
[root@xingdian ~]# [ -n "$var2" ];echo $?
1
[root@xingdian ~]# [ -n "$var3" ];echo $?
1
```
案例:
```shell
[root@xingdian ~]# [ "$USER" = "root" ];echo $?
0
[root@xingdian ~]# [ "$USER" = "alice" ];echo $?
1
[root@xingdian ~]# [ "$USER" != "alice" ];echo $?
0
[root@xingdian ~]# [ 1 -lt 2 -a 5 -gt 10 ];echo $?
1
[root@xingdian ~]# [ 1 -lt 2 -o 5 -gt 10 ];echo $?
0
[root@xingdian ~]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $?
1
[root@xingdian ~]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $?
0
[root@xingdian ~]# [ "$USER" = "root" ];echo $?
0
```
## 二:条件判断
#### 1.流程控制
在一个shell脚本中的命令执行顺序称作脚本的流大多数脚本会根据一个或多个条件来改变它们的流
流控制命令:能让脚本的流根据条件而改变的命令称为条件流控制命令
exit语句退出程序的执行并返回一个返回码返回码为0正常退出非0为非正常退出
条件判断if代码返回0表示真非0为假
#### 2.语法结构
单分支结构
```shell
if 条件测试
then 命令序列
fi
```
双分支结构
```shell
if 条件测试
then 命令序列
else 命令序列
fi
```
多分支结构
```shell
if 条件测试1
then 命令序列
[elif 条件测试2
then 命令序列
elif 条件测试3
then 命令序列]...
else 命令序列
fi
```
案例
```shell
if [ "$USER" = "root" ]
then
if [ $UID -eq 0 ]
then
echo "the user is root"
fi
elif
echo "……"
elif
echo "……"
else
echo "the user is not root"
echo "正在给用户授权"
fi
```
## 三:循环结构
#### 1.for循环
##### 语法结构
```shell
for i in (取值) 范围{1..20} zhangsan lisi wanger mazi ${array[*]}
for 变量名 [ in 取值列表 ]
do
循环体
done
```
##### 案例一
```shell
#!/bin/bash
# ping主机测试
for i in {70..100}
do
ping -c1 10.30.161.$i &> /dev/null
if [ $? -eq 0 ]
then
echo "10.30.161.$i is up" |tee -a ipup.txt
else
echo "10.30.161.$i is down" |tee -a ipdown.txt
fi
done
```
##### 案例二
```shell
#!/usr/bin/env bash
#批量添加账户
for i in {30..40}
do
useradd user$i && echo "123" | passwd --stdin user$i &>/dev/null
if [ $? -eq 0 ];then
echo "账户 user$i 添加成功"
else
echo "账户 user$i 添加失败"
fi
done
```
##### 案例三
```shell
#!/usr/bin/env bash
#批量删除账户
for i in {20..30}
do
userdel -r user$i &>/dev/null
[ $? -eq 0 ] && echo "账户 user$i 删除成功" || echo "账户 user$i 删除失败"
done
```
#### 2.while循环
不断重复的执行循环体中的语句,直到某个条件成立
循环次数不一定是固定的
##### 语法结构
当条件测试成立(条件测试为真),执行循环体
```
while 条件测试
do
循环体
done
```
##### 案例
```shell
echo "please enter a number between 5 and 10 :"
read var
while [[ $var != 0 ]]
do
if [ "$var" -lt 5 ]
then
echo "Too smail , Try again"
read var
elif [ "$var" -gt 10 ]
then
echo "Too big , Try again"
read var
else
echo "Congratulation! You are right."
exit 0;
fi
done
```
#### 3.until循环
当条件测试成立(条件测试为假),执行循环体
##### 语法结构
```shell
until 条件测试
do
循环体
done
```
##### 案例
```shell
#!/bin/bash
i=1
until [ "$i" -eq 21 ]
do
userdel -r user$i
let i++
done
```
## 四:匹配模式
#### 1.语法模式
```shell
read -p "请输入你的选项:" num
case num in
1) 选项
命令序列1 命令/if语句/for循环……
;;
模式2)
命令序列2
;;
模式3)
命令序列3
;;
*)
无匹配后命令序列
esac
```
##### 案例一
确定要继续删除吗 yes/no: " yes
##### 案例二
系统管理工具箱
```shell
Command action
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
Command (h for help): m
total used free shared buffers cached
Mem: 7628 840 6788 0 29 378
Swap: 2047 0 2047
```
#### 2.工具箱
```shell
#!/usr/bin/env bash
cat <<-EOF
+-------------------------------------------------------------------------+
| System_tools V1.0 |
+-------------------------------------------------------------------------+
| a. Stop And Disabled Firewalld. |
| b. Disabled SELinux Secure System. |
| c. Install Apache Service. |
| d. Quit |
+-------------------------------------------------------------------------+
EOF
printf "\e[1;31m Please input your select: \e[0m" && read var
case "$var" in
"a")
systemctl stop firewalld && systemctl disable firewalld
;;
"b")
sed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config
;;
"c")
yum -y install httpd httpd-tools
;;
"d")
exit
;;
*)
printf "请按照上方提供的选项输入!!!\n"
;;
esac
```
## 五:循环控制
#### 1.break
关键字用于跳出循环,执行循环后面的语句
案例
```shell
for i in {1..10}
do
if [ $i -eq 5 ]
then
break
fi
echo $i
done
# 输出结果为:
# 1
# 2
# 3
# 4
```
#### 2.continue
跳过当前循环中的剩余语句,直接进入下一次循环
案例
```shell
for i in {1..10}
do
if [ $i -eq 5 ]
then
continue
fi
echo $i
done
# 输出结果为:
# 1
# 2
# 3
# 4
# 6
# 7
# 8
# 9
# 10
```
#### 3.sleep
sleep 10 等待10秒再继续下一操作
## 六:格式化打印
printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等
#### 1.语法格式
```shell
[root@xingdiancloud ~]# printf format-string [arguments...]
• format-string: 为格式控制字符串
• arguments: 为参数列表
```
```shell
[root@xingdiancloud ~]# echo "Hello, Shell"
Hello, Shell
[root@xingdiancloud ~]# printf "Hello, Shell"
[root@xingdiancloud ~]# printf "Hello, Shell\n"
Hello, Shell
```
#### 2.案例
```shell
#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 张三 男 66.1234
printf "%-10s %-8s %-4.2f\n" 李四 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
```
#### 3.参数解释
%s 字符串
%f 小数
%d 数字
%-10s 指一个宽度为10个字符-表示左对齐,没有则表示右对齐)
%-4.2f 指格式化为小数,其中.2指保留2位小数
\f 换页
\n 换行
\r 回车
## 七:颜色
shell脚本中echo显示内容带颜色显示需要使用到-e参数
#### 1.语法格式
```shell
格式1echo -e "\033[背景颜色;字体颜色m 要输出的字符 \033[0m"
格式2echo -e "\e[背景颜色;字体颜色m 要输出的字符 \e[0m"
```
#### 2.案例
```shell
echo -e “\033[30m 黑色字 \033[0m”
echo -e “\033[31m 红色字 \033[0m”
echo -e “\033[32m 绿色字 \033[0m”
echo -e “\033[33m 黄色字 \033[0m”
echo -e “\033[34m 蓝色字 \033[0m”
echo -e “\033[35m 紫色字 \033[0m”
echo -e “\033[36m 天蓝字 \033[0m”
echo -e “\033[37m 白色字 \033[0m”
echo -e “\033[40;37m 黑底白字 \033[0m”
echo -e “\033[41;37m 红底白字 \033[0m”
echo -e “\033[42;37m 绿底白字 \033[0m”
echo -e “\033[43;37m 黄底白字 \033[0m”
echo -e “\033[44;37m 蓝底白字 \033[0m”
echo -e “\033[45;37m 紫底白字 \033[0m”
echo -e “\033[46;37m 天蓝底白字 \033[0m”
echo -e “\033[47;30m 白底黑字 \033[0m”
控制选项:
\033[0m关闭所有属性
\033[1m高亮显示加粗
\033[5m闪烁
```