shell/shell-流程控制.md
2025-03-28 20:10:14 +08:00

14 KiB
Raw Permalink Blame History

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

浮点数精度

  • 控制小数位数:%.NfN 为保留的小数位数)。
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"