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