537 lines
14 KiB
Markdown
537 lines
14 KiB
Markdown
<h2><center>Shell 流程控制</center></h2>
|
||
|
||
------
|
||
|
||
## 一:条件测试
|
||
|
||
### 1. 测试方法
|
||
|
||
| 方法 | 描述 |
|
||
| :--------------: | :----------------------------------------------------------: |
|
||
| test 测试表达式 | 利用test命令进行条件测试表达式,test命令与测试表达式之间至少有一个空格 |
|
||
| [ 测试表达式 ] | 通过[ ]中括号进行条件测试表达式,[]中括号边界与测试表达式之间至少有一个空格 |
|
||
| [[ 测试表达式 ]] | 通过[[ ]]双中括号进行条件测试表达式,[[ ]]双中括号与测试表达式之间至少有一个空格 |
|
||
| ((测试表达式)) | 通过(( ))双小括号进行条件测试表达式,( ))双小括号两端不需要空格,常用于整数对比 |
|
||
|
||
### 2. 文件测试
|
||
|
||
**语法**
|
||
|
||
```shell
|
||
# test 操作符 文件或目录
|
||
|
||
# [ 操作符 文件或目录]
|
||
```
|
||
|
||
| 操作符 | 描述 |
|
||
| ----------- | -------------------------------------------------- |
|
||
| **-d 文件** | 文件存在且为目录则为真 |
|
||
| **-f 文件** | 文件存在且为普通文件则为真 |
|
||
| **-e 文件** | 文件存在则为真,不辩别是目录还是文件 |
|
||
| **-s 文件** | 文件存在且文件大小不为0则为真 |
|
||
| **-r 文件** | 文件存在且可读则为真,与执行脚本的用户权限也有关 |
|
||
| **-w 文件** | 文件存在且可写则为真,与执行脚本的用户权限也有关 |
|
||
| **-x 文件** | 文件存在且可执行则为真,与执行脚本的用户权限也有关 |
|
||
| -L 文件 | 文件存在且为链接文件则为真 |
|
||
| f1 -nt f2 | 文件f1比文件f2新则为真,根据文件的修改时间计算 |
|
||
| f1 -ot f2 | 文件f1比文件f2旧则为真,根据文件的修改时间计算 |
|
||
|
||
示例:
|
||
|
||
```bash
|
||
[root@wxin ~]# test -d /home
|
||
[root@wxin ~]# echo $?
|
||
0
|
||
[root@wxin ~]# test -d /home111
|
||
[root@wxin ~]# echo $?
|
||
1
|
||
|
||
[root@wxin ~]# [ ! -d /ccc ]
|
||
[root@wxin ~]# [ ! -d /ccc ] && mkdir /ccc
|
||
[root@wxin ~]# [ -d /ccc ] || mkdir /ccc
|
||
```
|
||
|
||
### 3. 数字比较
|
||
|
||
**语法**
|
||
|
||
```shell
|
||
# test 数字 操作符 数字
|
||
# test $((变量)) 操作符 $((变量))
|
||
|
||
# [ 数字 操作符 数字 ]
|
||
# [ $((变量)) 操作符 $((变量)) ]
|
||
|
||
# [[ 数字 操作符 数字 ]]
|
||
# [[ $"变量" 操作符 $"变量" ]]
|
||
# [[ $((变量)) 操作符 $((变量)) ]]
|
||
|
||
# ((数字 操作符 数字))
|
||
# (($"变量" 操作符 $"变量"))
|
||
```
|
||
|
||
| **在[]、[[ ]]和test中使用** | **在(( ))中使用** | **说明** |
|
||
| --------------------------- | ----------------- | -------------------------------- |
|
||
| -eq | ==或= | 等于,全拼为equal |
|
||
| -ne | != | 不等于,全拼为not equal |
|
||
| -gt | > | 大于,全拼为greater than |
|
||
| -ge | >= | 大于等于,全拼为greater or equal |
|
||
| -lt | < | 小于,全拼为less than |
|
||
| -le | <= | 小于等于,全拼为less or equa |
|
||
|
||
**示例:**
|
||
|
||
```bash
|
||
[root@wxin ~]# test 1 -gt 0;echo $?
|
||
0
|
||
[root@wxin ~]# test $((num1)) -gt $((num2));echo $?
|
||
1
|
||
|
||
|
||
[root@wxin ~]# [ 1 -gt 0 ];echo $?
|
||
0
|
||
[root@wxin ~]# [ $((num1)) -gt $((num2)) ];echo $?
|
||
1
|
||
|
||
[root@wxin ~]# [[ 1 -lt 2 ]];echo $?
|
||
0
|
||
[root@wxin ~]# [[ $"num1" != $"num2" ]];echo $?
|
||
0
|
||
[root@wxin ~]# [[ $((num1)) -eq $((num2)) ]];echo $?
|
||
1
|
||
|
||
[root@wxin ~]# ((1 == 2));echo $?
|
||
1
|
||
[root@wxin ~]# (($"num1"<$"num2"));echo $?
|
||
0
|
||
```
|
||
|
||
### 4. 字符串比较
|
||
|
||
语法:
|
||
|
||
```shell
|
||
# test 参数 字符串
|
||
# test 字符串1 参数 字符串
|
||
|
||
# [ 参数 字符串 ]
|
||
# [ 字符串1 参数 字符串2 ]
|
||
```
|
||
|
||
| 参数 | 示例 | 功能 |
|
||
| --------- | ------ | -------------------------------------------- |
|
||
| **-z** | s1 | 如果字符串s1的长度为0,则测试条件为真 |
|
||
| **-n** | s1 | 如果字符串s1的长度大于0,则测试条件为真 |
|
||
| | s1 | 如果字符串s1不是空字符串,则测试条件为真 |
|
||
| **=或==** | s1=s2 | 如果s1等于s2,则测试条件为真,“=”前后应有空格 |
|
||
| **!=** | s1!=s2 | 如果s1不等于s2,则测试条件为真 |
|
||
| < | s1<s2 | 如果按字典顺序s1在s2之前,则测试条件为真 |
|
||
| > | s1>s2 | 如果按自定顺序s1在s2之后,则测试条件为真 |
|
||
|
||
**示例:**
|
||
|
||
```bash
|
||
[root@wxin ~]# str="12345"
|
||
[root@wxin ~]# str2="namespace"
|
||
|
||
[root@wxin ~]# test -z "$str";echo $?
|
||
1
|
||
[root@wxin ~]# test "$str";echo $?
|
||
0
|
||
|
||
[root@wxin ~]# [ -z "$str" ];echo $?
|
||
1
|
||
[root@wxin ~]# [ "$str" != "$str2" ];echo $?
|
||
0
|
||
```
|
||
|
||
### 5. 逻辑操作符
|
||
|
||
| **在[]和test中使用** | **在[[ ]]和(( ))中使用** | **说明** |
|
||
| -------------------- | ------------------------ | ---------------------------------- |
|
||
| -a | && | and,与,两端都为真,则结果为真 |
|
||
| -o | \|\| | or,或,两端有一个为真,则结果为真 |
|
||
| ! | ! | not,非,两端相反,则结果为真 |
|
||
|
||
## 二:条件判断
|
||
|
||
### 1. 流程控制
|
||
|
||
在一个shell脚本中的命令执行顺序称作脚本的流;大多数脚本会根据一个或多个条件来改变它们的流。
|
||
|
||
流控制命令:能让脚本的流根据条件而改变的命令称为条件流控制命令。
|
||
|
||
exit语句:退出程序的执行,并返回一个返回码,返回码为0正常退出,非0为非正常退出。
|
||
|
||
条件判断:if代码返回0表示真,非0为假。
|
||
|
||
### 2. 语法结构
|
||
|
||
**单分支结构**
|
||
|
||
```shell
|
||
if [ 条件判断式 ]; then
|
||
条件成立时,执行的程序
|
||
fi
|
||
```
|
||
|
||
**双分支结构**
|
||
|
||
```shell
|
||
if [ 条件判断式 ]; then
|
||
条件成立时,执行的程序
|
||
else
|
||
条件不成立时,执行的另一个程序
|
||
fi
|
||
```
|
||
|
||
**多分支结构**
|
||
|
||
```bash
|
||
if [ 条件判断式1 ]; then
|
||
当条件判断式1成立时,执行程序1
|
||
elif [ 条件判断式2 ]; then
|
||
当条件判断式2成立时,执行程序2
|
||
...省略更多条件....
|
||
else
|
||
当所有条件都不成立,最后执行此程序
|
||
fi
|
||
```
|
||
|
||
**case**
|
||
|
||
```shell
|
||
case $变量名 in
|
||
值1)
|
||
如果变量的值等于值1则执行指令1
|
||
;;
|
||
值2)
|
||
如果变量的值等于值2则执行指令2
|
||
;;
|
||
值3)
|
||
如果变量的值等于值3则执行指令3
|
||
;;
|
||
*)
|
||
如果变量的值不等于以上列出的任何值则执行默认指令
|
||
esac
|
||
```
|
||
|
||
## 三:循环结构
|
||
|
||
### 1. for 循环
|
||
|
||
**语法结构**
|
||
|
||
```bash
|
||
for 变量 in 值集合
|
||
do
|
||
执行命令
|
||
done
|
||
```
|
||
|
||
- for 每次从值集合中取一个值赋值给变量
|
||
- do - done 将赋值后的变量带入执行的命令得到执行结果
|
||
- 重复以上两个步骤,直到值集合中的值被一一获取赋值给变量的到所有结果,循环结束
|
||
|
||
### 2. while 循环
|
||
|
||
**语法结构**
|
||
|
||
```shell
|
||
while 条件测试
|
||
do
|
||
执行命令
|
||
done
|
||
```
|
||
|
||
- while 首先进行条件测试,如果传回值为0(条件测试为真),则进入循环,执行命令区域,否则不进入循环。
|
||
- 满足 while 测试条件,执行命令区域,直到 while 的测试条件不满足结束执行while循环(如果条件一直满足执行无穷循环)。
|
||
|
||
### 3. until 循环
|
||
|
||
**语法结构**
|
||
|
||
```shell
|
||
until 条件测试
|
||
do
|
||
执行命令
|
||
done
|
||
```
|
||
|
||
- until 条件测试结果为假(传回值不为0),就进入循环。
|
||
- 条件测试不满足,执行命令区域。直到 until 条件满足,结束执行until 循环(如果条件一直不满足则执行无穷循环)。
|
||
|
||
## 四:循环控制
|
||
|
||
### 1. break
|
||
|
||
**语法结构**
|
||
|
||
```shell
|
||
break n # n 表示跳出循环的次数, 如果省略n表示跳出单个循环
|
||
```
|
||
|
||
**示例**
|
||
|
||
```bash
|
||
for i in {1..3}; do
|
||
for j in {1..3}; do
|
||
for k in {1..3}; do
|
||
if [ $k -eq 2 ]; then
|
||
break 2
|
||
fi
|
||
echo "i=$i,j=$j,k=$k"
|
||
done
|
||
done
|
||
done
|
||
|
||
输出:
|
||
i=1, j=1, k=1
|
||
i=2, j=1, k=1
|
||
i=3, j=1, k=1
|
||
|
||
break 2 # 跳出2次循环
|
||
|
||
for i in {1..3}; do
|
||
for j in {1..3}; do
|
||
for k in {1..3}; do
|
||
if [ $k -eq 2 ]; then
|
||
break
|
||
fi
|
||
echo "i=$i,j=$j,k=$k"
|
||
done
|
||
done
|
||
done
|
||
|
||
输出:
|
||
i=1, j=1, k=1
|
||
i=1, j=2, k=1
|
||
i=1, j=3, k=1
|
||
i=2, j=1, k=1
|
||
i=2, j=2, k=1
|
||
i=2, j=3, k=1
|
||
i=3, j=1, k=1
|
||
i=3, j=2, k=1
|
||
i=3, j=3, k=1
|
||
```
|
||
|
||
### 2. continue
|
||
|
||
**语法结构**
|
||
|
||
```shell
|
||
continue n # 跳转到第n层封闭循环的下一个迭代
|
||
```
|
||
|
||
**示例**
|
||
|
||
```bash
|
||
for i in {1..3}; do
|
||
for j in {1..3}; do
|
||
if [ $j -eq 2]; then
|
||
continue
|
||
fi
|
||
echo "i=$i, j=$j"
|
||
done
|
||
done
|
||
|
||
输出:
|
||
i=1, j=1
|
||
i=1, j=3
|
||
i=2, j=1
|
||
i=2, j=3
|
||
i=3, j=1
|
||
i=3, j=3
|
||
|
||
for i in {1..3}; do
|
||
for j in {1..3}; do
|
||
if [ $j -eq 2]; then
|
||
continue 2
|
||
fi
|
||
echo "i=$i, j=$j"
|
||
done
|
||
done
|
||
|
||
输出:
|
||
i=1, j=1
|
||
i=2, j=1
|
||
i=3, j=1
|
||
```
|
||
|
||
### 3. exit
|
||
|
||
**语法格式**
|
||
|
||
```shell
|
||
exit # 退出循环
|
||
```
|
||
|
||
**示例:**
|
||
|
||
```bash
|
||
[root@wxin ~]# vim exit.sh
|
||
#!/bin/bash
|
||
for i in {1..5}; do
|
||
for j in {1..5}; do
|
||
if [ $j -eq 3 ]; then
|
||
exit
|
||
fi
|
||
echo "$i,$j"
|
||
done
|
||
done
|
||
[root@wxin ~]# bash exit.sh
|
||
1,1
|
||
1,2
|
||
```
|
||
|
||
## 五:shift 指令
|
||
|
||
shift 命令用于将参数列表 list 左移指定次数,最左端的那个参数就从列表中删除,其后边的参数继续进入循环。
|
||
|
||
shift[N]:用于将参量列表 list 左移指定次数,缺省为左移一次。
|
||
|
||
参量列表 list 一旦被移动,最左端的那个参数就从列表中删 除。while 循环遍历位置参量列表时,常用到 shift
|
||
|
||
**语法格式**
|
||
|
||
```shell
|
||
shift [n] # 默认 n=1,即左移 1 位;n 可以指定移动的位数
|
||
```
|
||
|
||
**示例**
|
||
|
||
```bash
|
||
# vim demo.sh
|
||
#!/bin/bash
|
||
while [ $# -gt 0 ]
|
||
do
|
||
echo $*
|
||
shift
|
||
done
|
||
|
||
# ./demo.sh a b c d e f g h
|
||
a b c d e f g h
|
||
b c d e f g h
|
||
c d e f g h
|
||
d e f g h
|
||
e f g h
|
||
f g h
|
||
g h
|
||
h
|
||
```
|
||
|
||
## 六:格式化打印
|
||
|
||
### 1. 语法格式
|
||
|
||
```shell
|
||
printf "格式字符串" 参数1 参数2 ...
|
||
```
|
||
|
||
- **格式字符串**:包含格式说明符(如 `%s`, `%d`, `%f`),用于定义输出样式。
|
||
- **参数**:按顺序替换格式字符串中的说明符。
|
||
- **自动换行**:`printf` **不会自动换行**,需手动添加 `\n`。
|
||
|
||
### 2. 格式说明符
|
||
|
||
| 说明符 | 用途 | 示例 |
|
||
| ------ | ------------- | --------------------- |
|
||
| `%s` | 字符串 | `printf "%s" "Hello"` |
|
||
| `%d` | 整数 | `printf "%d" 42` |
|
||
| `%f` | 浮点数 | `printf "%f" 3.14` |
|
||
| `%%` | 输出 `%` 符号 | `printf "%%"` |
|
||
| `\n` | 换行 | `printf "%d\n" 42` |
|
||
| `\f` | 换页 | `printf "%d\f" 42` |
|
||
| `\r` | 回车 | `printf "%d\r" 42` |
|
||
|
||
### 3. 格式控制
|
||
|
||
**字段宽度与对齐**
|
||
|
||
- **右对齐**:默认行为,指定宽度(如 `%10s`)。
|
||
- **左对齐**:用 `-` 符号(如 `%-10s`)。
|
||
- **填充字符**:默认用空格,可以用 `0` 填充数字(如 `%05d`)。
|
||
|
||
```bash
|
||
printf "右对齐: |%10s|\n" "Text" # | Text|
|
||
printf "左对齐: |%-10s|\n" "Text" # |Text |
|
||
printf "零填充: %05d\n" 7 # 00007
|
||
```
|
||
|
||
**浮点数精度**
|
||
|
||
- 控制小数位数:`%.Nf`(`N` 为保留的小数位数)。
|
||
|
||
```bash
|
||
printf "保留两位小数: %.2f\n" 3.1415 # 3.14
|
||
```
|
||
|
||
|
||
|
||
## 七:颜色
|
||
|
||
### 1. 语法格式
|
||
|
||
使用 `\033[` 或 `\e[` 作为转义序列的起始符,格式为:
|
||
|
||
```shell
|
||
echo -e "\033[样式代码;前景色;背景色m文本内容\033[0m"
|
||
```
|
||
|
||
- **`-e` 选项**:允许 `echo` 解析转义字符(必须加上)。
|
||
- **`\033[0m`**:重置所有样式(避免后续文本也应用颜色)。
|
||
|
||
### 2. 颜色代码表
|
||
|
||
**文本样式**
|
||
|
||
| 代码 | 样式 |
|
||
| ---- | -------------------------- |
|
||
| `0` | 重置所有样式 |
|
||
| `1` | 粗体 |
|
||
| `4` | 下划线 |
|
||
| `7` | 反显(反转前景色和背景色) |
|
||
|
||
**前景色(文字颜色)**
|
||
|
||
| 代码 | 颜色 | 代码(亮色) |
|
||
| ---- | ------ | ------------ |
|
||
| `30` | 黑色 | `90` |
|
||
| `31` | 红色 | `91` |
|
||
| `32` | 绿色 | `92` |
|
||
| `33` | 黄色 | `93` |
|
||
| `34` | 蓝色 | `94` |
|
||
| `35` | 品红色 | `95` |
|
||
| `36` | 青色 | `96` |
|
||
| `37` | 白色 | `97` |
|
||
|
||
**背景色**
|
||
|
||
| 代码 | 颜色 | 代码(亮色) |
|
||
| ---- | ------ | ------------ |
|
||
| `40` | 黑色 | `100` |
|
||
| `41` | 红色 | `101` |
|
||
| `42` | 绿色 | `102` |
|
||
| `43` | 黄色 | `103` |
|
||
| `44` | 蓝色 | `104` |
|
||
| `45` | 品红色 | `105` |
|
||
| `46` | 青色 | `106` |
|
||
| `47` | 白色 | `107` |
|
||
|
||
示例:
|
||
|
||
```bash
|
||
# 红色文字
|
||
echo -e "\033[31m这是红色文字\033[0m"
|
||
|
||
# 绿色背景 + 黄色文字
|
||
echo -e "\033[42;33m绿色背景上的黄色文字\033[0m"
|
||
|
||
# 粗体 + 蓝色文字
|
||
echo -e "\033[1;34m粗体蓝色文字\033[0m"
|
||
|
||
# 下划线 + 亮红色文字
|
||
echo -e "\033[4;91m下划线亮红色文字\033[0m"
|
||
```
|
||
|