Appearance
流程控制
- 状态:已验证
- 来源:对话整理
- 更新时间:2026-03-12
关键结论
- Shell 流程控制主要围绕条件判断、分支、循环、函数、退出码和逻辑运算展开。
if、case、for、while read -r和函数是最常见的控制结构。
详细分析
- Shell 中多数逻辑错误都来自判断条件、引号、循环读入方式或函数返回方式不清晰。
- Bash 的
[[ ... ]]和(( ... ))在表达复杂条件时更直观,但需要明确 Bash 依赖。
可执行步骤
- 先确定当前脚本是否允许使用 Bash 扩展语法。
- 依据具体场景选择
if、case、循环或函数。 - 涉及读文件时优先使用
IFS= read -r。 - 对函数结果区分“退出码返回”和“标准输出返回”。
命令 / 配置 / 代码
高频写法清单:
if [ ... ]; then ... fiif [[ ... ]]; then ... ficase ... in ... esacfor x in ...; do ... donewhile read -r line; do ... donename() { ... }cmd1 && cmd2
条件判断
if ...; then ... fi条件分支。[ ... ]传统测试表达式。[[ ... ]]Bash 扩展测试表达式,支持更强匹配能力。[ "$a" = "$b" ]字符串相等。[ "$a" != "$b" ]字符串不等。[ "$n" -lt 10 ]数值比较。[ -f "$file" ]判断普通文件是否存在。[ -d "$dir" ]判断目录是否存在。[ -n "$x" ]字符串非空。[ -z "$x" ]字符串为空。[[ "$name" == a* ]]Bash 模式匹配。[[ "$text" =~ ^[0-9]+$ ]]Bash 正则匹配。(( n > 0 ))算术条件判断。
bash
if [ -f "$file" ]; then
echo "file exists"
fibash
if [ "$a" = "$b" ]; then
echo "equal"
elif [ "$a" != "$b" ]; then
echo "not equal"
else
echo "unknown"
fibash
if [[ -f "$file" && "$name" == a* ]]; then
echo "match"
ficase 分支
case value in ... esac多分支匹配。pattern)匹配某个模式。*)默认分支。;;结束当前分支。
bash
case "${1:-}" in
start)
echo "start"
;;
stop)
echo "stop"
;;
*)
echo "unknown"
;;
esacfor 循环
for item in list; do ... done遍历列表。for ((i = 0; i < n; i++)); do ... doneC 风格计数循环。
bash
for f in *.md; do
echo "$f"
donebash
for ((i = 0; i < 5; i++)); do
echo "$i"
doneselect 选择循环
select item in list; do ... done生成简单菜单,适合交互脚本。break退出选择循环。
bash
select action in start stop quit; do
case "$action" in
start|stop) echo "$action" ;;
quit) break ;;
*) echo "invalid" ;;
esac
donewhile 与 read
while condition; do ... done条件循环。read -r line读取一行文本,不处理反斜杠转义。IFS= read -r line保留行首尾空白并安全读取整行。done < input.txt从文件重定向输入。
bash
while read -r line; do
echo "$line"
done < input.txtbash
while IFS= read -r line; do
echo "$line"
done < input.txt函数
name() { ... }定义函数。local var="x"定义函数局部变量。return 0返回退出码。echo ...函数若需“返回字符串”,通常通过标准输出返回。
bash
log() {
echo "[INFO] $*"
}bash
add() {
local a="$1"
local b="$2"
echo $((a + b))
}source 与脚本执行
./script.sh启动子进程执行脚本。bash script.sh用 Bash 执行脚本。source script.sh在当前 shell 中加载脚本。. script.shsource的简写。
bash
source ./env.sh
. ./env.sh
bash ./build.sh退出码
exit 0整个脚本成功退出。exit 1整个脚本失败退出。return 0函数成功返回。return 1函数失败返回。"$?"上一条命令的退出码。
bash
echo "$?"逻辑运算
cmd1 && cmd2前一条成功才执行后一条。cmd1 || cmd2前一条失败才执行后一条。! cmd1逻辑取反。
bash
cmd1 && cmd2
cmd1 || cmd2
! cmd1子 shell 与命令组
( cmd1; cmd2 )在子 shell 中执行命令组。{ cmd1; cmd2; }在当前 shell 中执行命令组。
bash
(cd /tmp && pwd)
{ echo "a"; echo "b"; }风险与注意事项
[ ... ]两侧必须有空格,例如[ -f "$x" ]。[[ ... ]]是 Bash 写法,不是所有/bin/sh都支持。- 逐行读取文本优先使用
read -r。 set -e在某些复合语句中的行为并不直观,关键脚本应结合退出码显式处理。