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

Shell 分支与循环

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

if

if 根据 condition 的返回值判断是否要执行该分支,如果 condition 返回 0,则为真,否则为假。

一般使用/bin/test/bin/[[[进行条件测试,具体的命令用法已在前文给出,不再复述。

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 都会先展开里面的元素(如果元素内容含空白符,则自动加上引号)

不光在 foreach 中是这样,在进行 “参数转发” 时也经常使用 "$@""${array[@]}" 等表达式,它们也会被自动展开,简单例子:

test.sh

1
2
3
4
5
6
7
#!/bin/bash
function 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 返回 0,则继续循环,否则退出循环。

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      # 因为 /bin/true 命令总是返回 0
    ...
done

## 无限循环 - 2
while :; do         # 因为 : built-in 命令总是返回 0
    ...
done

## 无限循环 - 3
for ((;;)) do       # for 无限循环
    ...
done

until

如果 condition 返回非 0,则继续循环,否则退出循环,和 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 变量