shell编程中的循环结构和条件结构
1 循环结构
1.1 for 循环
- 使用列表进行循环
#!/bin/bash
for fruit in apple banana cherry
do
echo "I like $fruit"
Done
- 使用范围进行循环
#!/bin/bash
for i in {1..5}
do
echo "Number $i"
Done
- 使用C语言风格的循环
#!/bin/bash
for ((i=0; i<5; i++))
do
echo "C style loop: $i"
Done
1.2 while 循环
while 循环在指定条件为真时重复执行命令。
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "Count is $count"
count=$((count + 1))
Done
使用while循环读取文件的每一行
#!/bin/bash
#设置要读取的文件名
filename="example.txt"
# 使用 while 循环读取文件中的每一行。 IFS= 设置内部字段分隔符为空,
# 以确保读取整行内容。read -r line 读取一行并存储在变量 line 中。
# read -r: 使用 -r 选项,防止反斜杠被解释为转义字符。
while IFS= read -r line
do
echo "Read line: $line"
done < "$filename"
# do ... done < "$filename":从文件中读取内容并执行循环体内的命令。
1.3 until 循环
until 循环在指定条件为假时重复执行命令(与 while 循环相反)。
#!/bin/bash
count=1
until [ $count -gt 5 ]
do
echo "Count is $count"
count=$((count + 1))
Done
1.4 循环控制
1.4.1 break 语句
break 语句用于提前终止循环。
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 5 ];
then
break
fi
echo "Number $i"
done
1.4.2 continue 语句
continue 语句用于跳过本次循环的剩余部分,立即开始下一次循环。
#!/bin/bash
for i in {1..5}do
if [ $i -eq 3 ]; then
continue
fi
echo "Number $i"
Done
1.4.3 Exit 终止脚本的执行
在 Shell 脚本中,exit 命令用于终止脚本的执行,并可以返回一个状态码给调用它的环境。状态码通常用于指示脚本的执行结果:0 表示成功,非零值表示某种错误或特殊状态。使用 exit 时,可以指定返回的状态码,如果不指定,默认返回上一个命令的退出状态。
1. 根据条件退出
#!/bin/bash
echo "请输入一个数字:"
read number
if [ "$number" -lt 10 ]; then
echo "输入的数字小于10,退出状态码为1"
exit 1
else
echo "输入的数字大于等于10,正常退出"
exit 0
fi
2. 在函数中使用 exit
#!/bin/bash
check_file() {
if [ ! -f "$1" ]; then
echo "文件 $1 不存在"
exit 2 # 退出并返回状态码2
else
echo "文件 $1 存在"
fi
}
check_file "/path/to/file"
3. 循环控制中的exit
在 Shell 脚本的循环中使用 exit 可以在满足特定条件时终止整个脚本的执行,并返回一个状态码。这在处理错误条件或满足某个退出条件时非常有用。下面介绍如何在不同类型的循环中使用 exit,并提供相应的示例。
在 for 循环中使用 exit
#!/bin/bash
# 使用 for 循环遍历一个列表
for i in {1..10}
do
if [ $i -eq 5 ];
then
echo "遇到 $i,退出整个脚本"
exit 1 # 退出脚本,返回状态码1
fi
echo "Number $i"
done
运行这个脚本时,当 i 等于 5 时,脚本将输出一条消息并退出整个脚本。状态码为 1 表示脚本非正常退出。
4. 捕获退出状态
可以在调用脚本后捕获其退出状态,并根据状态码执行相应的操作:
#!/bin/bash
./script_with_exit.sh
status=$?
if [ $status -eq 0 ]; then
echo "脚本执行成功"else
echo "脚本执行失败,退出状态码为 $status"
fi
在这个示例中,script_with_exit.sh 是一个包含 exit 命令的脚本。通过捕获其退出状态,可以根据状态码采取不同的操作。
1.4.4 shift将位置参数左移
在 Shell 脚本中,shift 命令用于参数处理,它会将所有位置参数左移一个位置。使用 shift 可以方便地迭代处理所有传递给脚本的参数。
循环控制中的shift
使用 shift 处理命令行参数
以下是一个示例脚本,演示如何使用 shift 命令在循环中处理参数。
#!/bin/bash
# 打印所有传递的参数
echo "传递的所有参数: $@"
# 处理每一个参数
while [ $# -gt 0 ];
do
echo "当前参数: $1"
# 在这里可以对 $1 执行任何操作
shift # 左移参数
Done
运行这个脚本:
./script.sh arg1 arg2 arg3
输出:
makefile
传递的所有参数: arg1 arg2 arg3
当前参数: arg1
当前参数: arg2
当前参数: arg3
以下是一个更复杂的示例,演示如何使用 shift 命令在 while 循环中处理多个命令行参数,并对特定参数执行不同的操作。
#!/bin/bash
# 初始参数计数
echo "总共有 $# 个参数"
while [ $# -gt 0 ]; do
case $1 in
-h|--help)
echo "显示帮助信息"
;;
-f|--file)
echo "处理文件: $2"
shift # 左移一次,跳过文件名参数
;;
-v|--verbose)
echo "启用详细模式"
;;
*)
echo "未知参数: $1"
;;
esac
shift # 左移参数
done
运行这个脚本:
./script.sh -h -f myfile.txt -v unknown
输出:
makefile
总共有 5 个参数
显示帮助信息处理文件: myfile.txt
启用详细模式未知参数: unknown
2. Shell编程之条件结构
2.1 Shell条件测试语法
- test 测试表达式
语法
if test condition;
then
# 执行的命令
else
# 执行的命令
fi
示例:
if test -f "example.txt";
then
echo "文件存在且是普通文件"
fi
2. [] 测试表达式
test 命令的简写形式
语法:
if [ condition ];
then
# 执行的命令
fi
示例:
if [ -f "example.txt" ];
then
echo "文件存在且是普通文件"
fi
3. [[ ]] 测试表达式
[[ ]] 符号进行条件测试,这是增强的测试表达式,可以使用更复杂的条件判断,包括正则表达式和模式匹配。它们之间的条件可以不需要转义。
语法:
if [[ condition ]];
then
# 执行的命令
fi
例如:
if [[ -f "example.txt" && -r "example.txt" ]];
then
echo "文件存在且可读"
fi
4. (( )) 测试表达式
使用 (( )) 符号进行整数条件测试,适用于对整数值进行比较和算术运算。(( )) 符号内的表达式可以不需要使用 $ 符号来引用变量。
语法:
if (( condition ));
then
# 执行的命令
fi
示例:
num1=10
num2=20
if (( num1 < num2 ));
then
echo "num1 小于 num2"
fi
总结
- test 和 [] 用于基本的条件测试,功能类似,方括号更加简洁。
- [[ ]] 提供了更强大的测试功能,支持更复杂的条件判断。
- (( )) 专用于整数条件测试和算术运算。
2.2 shell测试操作符
2.2.1 文件测试操作符
操作符 | 含义 |
---|---|
-d 文件 | 文件存在且为目录则为真 |
-f 文件 | 文件存在且为普通文件则为真 |
-e 文件 | 文件存在则为真,不管是目录还是文件 |
-s 文件 | 文件存在且大小不为0则为真 |
-r 文件 | 文件存在且可读则为真,与执行脚本的用户权限也有关 |
-w 文件 | 文件存在且可写则为真,与执行脚本的用户权限也有关 |
-x 文件 | 文件存在且可执行则为真,与执行脚本的用户权限也有关 |
-L 文件 | 文件存在且为链接文件则为真 |
f1 -nt f2 | 文件f1比文件f2新则为真,根据文件的修改时间计算 |
f1 -ot f2 | 文件f1比文件f2旧则为真,根据文件的修改时间计算 |
2.2.2 字符串测试操作符
操作符 | 含义 |
---|---|
= | 检查字符串是否相等 |
!= | 检查字符串是否不相等 |
-z | 检查字符串是否为空 |
-n | 检查字符串是否非空 |
< | 检查字符串是否按字典序小于另一字符串 |
> | 检查字符串是否按字典序大于另一字符串 |
-eq | 检查两个数字是否相等 |
-ne | 检查两个数字是否不相等 |
-lt | 检查第一个数字是否小于第二个数字 |
-gt | 检查第一个数字是否大于第二个数字 |
=~ | 正则表达式匹配 |
* | 通配符匹配 |
2.2.3 数值测试操作符
在[]和test中使用 | 描述 | 在[[]]和(())中使用 |
---|---|---|
-eq | 检查两个数字是否相等 | = |
-ne | 检查两个数字是否不相等 | != |
-gt | 检查第一个数字是否大于第二个数字 | > |
-lt | 检查第一个数字是否小于第二个数字 | < |
-ge | 检查第一个数字是否大于或等于第二个数字 | >= |
-le | 检查第一个数字是否小于或等于第二个数字 | <= |
2.2.4 逻辑操作符
操作符 | 描述 |
---|---|
&& | 仅在两个条件都为真时返回真。 |
! | 取反,即将真变为假,假变为真。 |
-a | 仅在两个条件都为真时返回真(test 命令中使用)。 |
-o | 仅在两个条件中至少有一个为真时返回真(test 命令中使用)。 |
2.3 Case语句
基本语法
case 值 in
模式1)
# 当值匹配模式1时执行的命令
;;
模式2)
# 当值匹配模式2时执行的命令
;;
*)
# 当值不匹配任何模式时执行的命令
;;esac
说明
- 值 是需要进行匹配的变量或表达式。
- 模式 可以包含通配符(例如*、?、[…]等)。
- 每个模式之后必须跟随一个右括号 )。
- 每个模式的命令列表必须以双分号 ;; 结尾。
- *代表默认分支,当值不匹配任何模式时执行。
示例
#!/bin/bash
echo "请输入一个文件名:"
read filename
case $filename in
*.jpg | *.jpeg)
echo "这是一个JPEG图片文件"
;;
*.png)
echo "这是一个PNG图片文件"
;;
*.gif)
echo "这是一个GIF图片文件"
;;
*.txt)
echo "这是一个文本文件"
;;
*)
echo "未知的文件类型"
;;
esac