for 循环

bash shell 中 for 命令的基本格式。

1
2
3
for var in list; do
commands
done

在 commands 中, $var 变量包含着这次迭代对应的当前列表项中的值。 在 list 参数中,你需要提供迭代中要用到的一系列值。可以通过几种不同的方法指定列表中的值。下面介绍几种方式

读取列表中的值

for 命令最基本的用法就是遍历 for 命令自身所定义的一系列值。for 循环假定每个值都是用空格分割的.

1
2
3
4
for name in xiaoming zhangsan lisi wangwu
do
echo "the name is " $name
done

两个注意事项:

  1. 列表值中有单引号

    shell 看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值

    解决方法:

    1. 使用 \对单引号进行转义
    2. 使用双引号将该列表值括起来 在某个值两边使用双引号时,shell 并不会将双引号当成值的一部分。
  2. 列表值中含有空格

    解决方法:使用双引号将该列表值括起来

从变量读取列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat test.sh
#!/bin/bash
list="item1 item2 item3"
list=$list" item4"
for item in $list
do
echo "this is $item"
done

# violetv at manjaro in ~/codespace/sh_test [21:38:43]
$ ./test.sh
this is item1
this is item2
this is item3
this is item4

$list 变量包含了用于迭代的标准文本值列表。代码还用了另一个赋值语句向 $list 变量包含的已有列表中添加(或者说是拼接)了一个值。这是向变量中存储的已有文本字符串尾部添加文本的一个常用方法。

从命令读取值

结合命令替换,从遍历命令的结果

1
2
3
4
#!/bin/bash
for i in $(ls ~);do
echo "$i"
done

生成序列

序列表达式

序列表达式是花括号展开(brace expansion)特性的一个功能。

序列表达式的语法是:{<START>..<END>[..<INCR>]}

示例:

1
2
3
for i in {a..g};do
echo $i
done

seq

seq 命令用来生成序列:

NAME seq - print a sequence of numbers

SYNOPSIS seq [OPTION]... LAST seq [OPTION]... FIRST LAST seq [OPTION]... FIRST INCREMENT LAST

题目与题解

题目:Looping and Skipping

题解

思路是直接生成跳过偶数的序列。当然,直接生成全序列,然后判断也可。

  1. 花括号扩展的序列生成表达式(最佳)

    Using in-built ranges (like for x in {1..99..2}) is much faster.

    1
    2
    3
    4
    #!/bin/bash
    for num in {1..99..2};do
    echo $num
    done

    Note that bash doesn't support variables in brace range expansions.

    题目练习:Compute the Average

  2. seq 生成序列

    1
    2
    3
    4
    #!/bin/bash
    for num in $(seq 1 2 99);do
    echo $num
    done

  3. 全序列,判断

    1
    2
    3
    4
    5
    6
    #!/bin/bash
    for i in {1..99}; do
    if test $(expr $i % 2) -ne 0; then
    echo $i
    fi
    done

用通配符读取目录

进行此操作时,必须在文件名或路径名中使用通配符。它会强制 shell 使用文件扩展匹配。文件扩展匹配是生成匹配指定通配符的文件名或路径名的过程。 如果不知道所有的文件名,这个特性在处理目录中的文件时就非常好用。

例如:for file in /home/rich/test/*

C 语言风格的 for 命令

C 语言风格的 for 命令也允许为迭代使用多个变量。循环会单独处理每个变量,你可以为每个变量定义不同的迭代过程。尽管可以使用多个变量,但你只能在 for 循环中定义一种条件。

1
2
3
4
for (( variable assignment ; condition ; iteration process )); do
commands
done

示例:

1
2
3
4
5
6
7
8
9
for (( i=1; i <= 10; i++ ))
do
echo "The next number is $i"
done

for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done

while

格式:

1
2
3
4
while test command
do
other commands
done

while 命令中定义的 test command 和 if-then 语句中的格式一模一样。最常见的 test command 的用法是用方括号来检查循环命令中用到的 shell 变量的值

until

until 命令要求你指定一个通常返回非零退出状态码的测试命令。只有测试命令的退出状态码不为 0,bash shell 才会执行循环中列出的命令。 一旦测试命令返回了退出状态码 0,循环就结束了。

格式:

1
2
3
until test commands
do
done

处理循环

  1. breakcontinue 关键字和其他语言一样用法
  2. 处理循环的输出 可以对循环的输出使用管道或进行重定向。这可以通过在 done 命令之后添加一个处理命令来实现。

参考资料

  1. Linux 命令行与 Shell 脚本编程大全