14 KiB
14 KiB
Shell 流程控制
一:条件测试
1. 测试方法
方法 | 描述 |
---|---|
test 测试表达式 | 利用test命令进行条件测试表达式,test命令与测试表达式之间至少有一个空格 |
[ 测试表达式 ] | 通过[ ]中括号进行条件测试表达式,[]中括号边界与测试表达式之间至少有一个空格 |
测试表达式 | 通过 双中括号进行条件测试表达式, 双中括号与测试表达式之间至少有一个空格 |
((测试表达式)) | 通过(( ))双小括号进行条件测试表达式,( ))双小括号两端不需要空格,常用于整数对比 |
2. 文件测试
语法
# test 操作符 文件或目录
# [ 操作符 文件或目录]
操作符 | 描述 |
---|---|
-d 文件 | 文件存在且为目录则为真 |
-f 文件 | 文件存在且为普通文件则为真 |
-e 文件 | 文件存在则为真,不辩别是目录还是文件 |
-s 文件 | 文件存在且文件大小不为0则为真 |
-r 文件 | 文件存在且可读则为真,与执行脚本的用户权限也有关 |
-w 文件 | 文件存在且可写则为真,与执行脚本的用户权限也有关 |
-x 文件 | 文件存在且可执行则为真,与执行脚本的用户权限也有关 |
-L 文件 | 文件存在且为链接文件则为真 |
f1 -nt f2 | 文件f1比文件f2新则为真,根据文件的修改时间计算 |
f1 -ot f2 | 文件f1比文件f2旧则为真,根据文件的修改时间计算 |
示例:
[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. 数字比较
语法
# test 数字 操作符 数字
# test $((变量)) 操作符 $((变量))
# [ 数字 操作符 数字 ]
# [ $((变量)) 操作符 $((变量)) ]
# [[ 数字 操作符 数字 ]]
# [[ $"变量" 操作符 $"变量" ]]
# [[ $((变量)) 操作符 $((变量)) ]]
# ((数字 操作符 数字))
# (($"变量" 操作符 $"变量"))
在[]、 和test中使用 | 在(( ))中使用 | 说明 |
---|---|---|
-eq | ==或= | 等于,全拼为equal |
-ne | != | 不等于,全拼为not equal |
-gt | > | 大于,全拼为greater than |
-ge | >= | 大于等于,全拼为greater or equal |
-lt | < | 小于,全拼为less than |
-le | <= | 小于等于,全拼为less or equa |
示例:
[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. 字符串比较
语法:
# 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之后,则测试条件为真 |
示例:
[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. 语法结构
单分支结构
if [ 条件判断式 ]; then
条件成立时,执行的程序
fi
双分支结构
if [ 条件判断式 ]; then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
多分支结构
if [ 条件判断式1 ]; then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]; then
当条件判断式2成立时,执行程序2
...省略更多条件....
else
当所有条件都不成立,最后执行此程序
fi
case
case $变量名 in
值1)
如果变量的值等于值1则执行指令1
;;
值2)
如果变量的值等于值2则执行指令2
;;
值3)
如果变量的值等于值3则执行指令3
;;
*)
如果变量的值不等于以上列出的任何值则执行默认指令
esac
三:循环结构
1. for 循环
语法结构
for 变量 in 值集合
do
执行命令
done
- for 每次从值集合中取一个值赋值给变量
- do - done 将赋值后的变量带入执行的命令得到执行结果
- 重复以上两个步骤,直到值集合中的值被一一获取赋值给变量的到所有结果,循环结束
2. while 循环
语法结构
while 条件测试
do
执行命令
done
- while 首先进行条件测试,如果传回值为0(条件测试为真),则进入循环,执行命令区域,否则不进入循环。
- 满足 while 测试条件,执行命令区域,直到 while 的测试条件不满足结束执行while循环(如果条件一直满足执行无穷循环)。
3. until 循环
语法结构
until 条件测试
do
执行命令
done
- until 条件测试结果为假(传回值不为0),就进入循环。
- 条件测试不满足,执行命令区域。直到 until 条件满足,结束执行until 循环(如果条件一直不满足则执行无穷循环)。
四:循环控制
1. break
语法结构
break n # n 表示跳出循环的次数, 如果省略n表示跳出单个循环
示例
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
语法结构
continue n # 跳转到第n层封闭循环的下一个迭代
示例
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
语法格式
exit # 退出循环
示例:
[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
语法格式
shift [n] # 默认 n=1,即左移 1 位;n 可以指定移动的位数
示例
# 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. 语法格式
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
)。
printf "右对齐: |%10s|\n" "Text" # | Text|
printf "左对齐: |%-10s|\n" "Text" # |Text |
printf "零填充: %05d\n" 7 # 00007
浮点数精度
- 控制小数位数:
%.Nf
(N
为保留的小数位数)。
printf "保留两位小数: %.2f\n" 3.1415 # 3.14
七:颜色
1. 语法格式
使用 \033[
或 \e[
作为转义序列的起始符,格式为:
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 |
示例:
# 红色文字
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"