Shell 脚本里的流程控制
写 Shell 脚本时,光有一堆命令堆砌可不行。就像开车得有方向盘和刹车,脚本也需要流程控制来决定命令的执行顺序。今天咱们就聊聊 Shell 里那些让命令 "听话" 的家伙 —— 条件判断和循环语句。
一、用 if 语句做选择题
生活中总遇到 "如果... 就..." 的场景,脚本里也一样。比如判断一个文件是否存在,存在就做点啥,不存在就另做点啥。
最基础的 if 语句长这样:
if [ 条件判断 ]; then# 条件成立时执行的命令fi
注意哦,[ ]前后的空格不能少,这是 Shell 的语法规定,少了就会报错。
举个实际例子,判断当前目录下是否有test.txt:
if [ -f "test.txt" ]; thenecho "找到test.txt啦,内容是:"cat test.txtelseecho "没找到test.txt,我来创建一个"touch test.txtecho "新文件创建于$(date)" > test.txtfi
这里的-f是判断文件是否存在且为普通文件的测试选项。Shell 里还有很多这类测试选项,比如-d判断目录,-z判断字符串是否为空,-eq比较数字是否相等。
如果需要多个条件判断,还可以用elif来扩展:
read -p "请输入你的分数(0-100):" scoreif [ $score -ge 90 ]; thenecho "优秀!"elif [ $score -ge 60 ]; thenecho "及格啦"elseecho "继续努力"fi
二、case 语句处理多选一
当选项特别多时,用一堆elif会显得很乱。这时候case语句就派上用场了,有点像考试里的单选题。
它的基本结构是:
case 变量 in模式1)# 匹配模式1时执行;;模式2)# 匹配模式2时执行;;*)# 所有模式都不匹配时执行;;esac
比如做个简单的菜单:
echo "请选择操作:"echo "1. 查看当前目录"echo "2. 显示系统时间"echo "3. 退出"read -p "输入数字1-3:" numcase $num in1)ls -l;;2)date;;3)echo "再见!"exit 0;;*)echo "输入有误哦,请重新运行脚本";;esac
这里的*就像通配符,匹配所有没被前面模式匹配到的情况。每个模式结束后的;;不能少,相当于其他语言里的break。
三、for 循环遍历一切
需要重复执行相同操作时,循环就该登场了。for循环特别适合处理列表里的每个元素。
最常用的遍历方式:
for 变量 in 列表; do# 循环体命令done
比如批量处理当前目录的 txt 文件:
for file in *.txt; do# 跳过空文件if [ -s "$file" ]; thenecho "文件$file有内容,行数是:"wc -l "$file"elseecho "文件$file是空的,删除它"rm "$file"fidone
这里的*.txt会自动展开成当前目录所有 txt 文件的列表,for循环会逐个处理。
四、while 循环处理未知次数的任务
当不知道循环要执行多少次,只知道结束条件时,while循环就很合适。比如不断读取用户输入直到用户输入 "quit"。
echo "请输入内容(输入quit退出):"while read input; doif [ "$input" = "quit" ]; thenecho "退出程序"break # 跳出循环fiecho "你输入的是:$input,长度是${#input}"done
这个脚本会一直等待用户输入,直到输入 "quit" 才结束。${#input}是获取字符串长度的语法。
另一个常见用法是读取文件的每一行:
# 假设file.txt里有多个网址while read url; doecho "正在访问$url..."curl -s "$url" > /dev/null # 静默访问if [ $? -eq 0 ]; then # $?是上一条命令的退出状态,0表示成功echo "$url 可以访问"elseecho "$url 无法访问"fidone < file.txt # 从file.txt读取内容
五、一些实用技巧
- 条件判断的组合:可以用&&(与)和||(或)组合多个条件
# 判断文件存在且有执行权限if [ -f "script.sh" ] && [ -x "script.sh" ]; then./script.shfi
- 循环控制:除了break,还有continue可以跳过当前循环的剩余部分,直接进入下一次循环
for i in {1..10}; doif [ $((i%2)) -eq 0 ]; thencontinue # 跳过偶数fiecho "奇数:$i"done
- 简化的条件执行:单行写法可以用&&和||代替简单的 if-else
# 等同于if [ -f "file.txt" ]; then cat file.txt; else echo "no file"; fi[ -f "file.txt" ] && cat file.txt || echo "no file"