首页 Shell 分支与循环
文章
取消

Shell 分支与循环

分支/循环语句块不可为空,如果不需要就不要写,如果确实需要,就用:内置命令占位。

if

if 根据 condition 的 退出状态码 决定是否执行,0 是 (条件成立),非 0 是 (条件不成立)。

常用的条件测试命令有:test[[[,它们的具体用法已在前一篇中给出,这里就不再复述了。

1
2
3
4
5
6
if condition; then
    command1
    command2
    ...
    commandN
fi

if…else

如果 condition 成立,则执行 if 分支,否则执行 else 分支。

1
2
3
4
5
6
7
8
9
if condition; then
    command1
    ...
    commandN
else
    command1
    ...
    commandN
fi

if…elif…else

从上至下依次评估,如果条件成立,则执行对应分支(匹配结束);

如果所有条件都不成立,则执行 else 分支(当然,可以没有 else 分支)。

1
2
3
4
5
6
7
8
9
if condition; then
    ...
elif condition; then
    ...
elif condition; then
    ...
else
    ...
fi

foreach

用于遍历(枚举)指定的元素列表。

  • 传递给 foreach 的元素列表其实和传递给命令的参数列表一样,会使用空白符进行分词
  • 如果元素内容包含空白符(如空格),必须使用引号包围,否则会被作为多个元素处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## 指定元素列表(空格隔开,如果元素内容包含空白符,请使用引号包围)
for var in item1 item2 item3 ... itemN; do
    command1
    command2
    ...
    commandN
done

## 如果省略 in 列表,则遍历参数(脚本命令行参数或函数的位置参数)
for arg; do
    echo "$arg"
done

## 遍历数组 (双引号)
for elem in "${array[@]}"; do
    command1
    command2
    ...
    commandN
done

## 遍历参数 (双引号)
for arg in "$@"; do
    command1
    command2
    ...
    commandN
done

关于 "${array[@]}""$@"

必须使用双引号包围,否则无法正确处理数组元素/位置参数中包含空白符的情况(会被当做分隔符)。

只要是双引号中带 @ 的表达式,shell 都会先展开里面的元素,如 "$@",相当于 "$1" "$2" "$3" ...

在进行 “参数转发” 时也经常使用 "$@""${array[@]}" 等表达式,它们也会被自动展开,例如:

test.sh

1
2
3
4
5
6
7
8
9
#!/bin/bash
main() {
    for arg in "$@"; do
        echo "$arg"
    done
}
main $@   # 没引号
echo '-----------'
main "$@" # 双引号

执行结果

1
2
3
4
5
6
7
8
9
10
11
$ ./test.sh 1 2 3 '4 5'
1
2
3
4
5
-----------
1
2
3
4 5

for

C/C++ 风格的 for() 循环,使用双重圆括号。

1
2
3
for ((i = 0; i < 10; i++)); do
    echo $i
done

while

如果 condition 成立,则执行循环体,否则退出循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while condition; do
    ...
done

## 无限循环 - 1
while true; do      # 因为 true 总是返回真
    ...
done

## 无限循环 - 2
while :; do         # 因为 : 总是返回真
    ...
done

## 无限循环 - 3
for ((;;)) do       # for 无限循环 (C/C++ 风格)
    ...
done

until

如果 condition 不成立,则执行循环体,否则退出循环。和 while 相反。

1
2
3
until condition; do
    ...
done

case

if…elif…elif…else 的简化直观版本,相当于 C 语言的 switch 语句。

globbing 即 shell 通配符,case 还在此基础上添加了对|选择元字符的支持。

因此,在 case 中,支持*?[][^]|五种模式匹配元字符。

解释一下|,它和 regex 中的|是一样的,的意思,用来选择多个模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
case var in
globbing1)
    command1
    ...
    commandN
    ;;
globbing2)
    command1
    ...
    commandN
    ;;
globbing3)
    command1
    ...
    commandN
    ;;
*)
    command1
    ...
    commandN
    ;;
esac

break、continue

  • break:跳出当前循环,执行循环后面的语句;
  • continue:结束本轮循环,开始执行下轮循环。

这两个关键字可用于forwhileuntil中。

breakcontinue 后面可以接一个整数(大于 0),即 break Ncontinue N

这个 N 是什么意思呢?它表示要跳出几层循环,N 默认为 1,即只跳出当前这层循环。例子:

test.sh

1
2
3
4
5
6
7
#!/bin/bash
for ((i = 0; i < 3; i++)); do
    for ((j = 0; j < 3; j++)); do
        [ "$i" -eq 1 ] && continue 2
        echo "$i $j"
    done
done
1
2
3
4
5
6
7
$ ./test.sh
0 0
0 1
0 2
2 0
2 1
2 2
本文由作者按照 CC BY 4.0 进行授权

Shell 打印输出

Shell IFS 变量