Linux结构化命令之循环语句

1 for 命令

for 命令的基本格式:

for var in list
do
    commands
done

list 参数中, 需要提供迭代中要用到的 一系列值.
每次迭代, 变量 $var 会包含 list 的当前值.
dodone 语句之间是每次迭代需要执行的命令(组).

for 命令读取列表中的值:

$ cat temp.sh
#!/bin/bash
for var in hello world; do
    echo value: $var
done

$ ./temp.sh
value: hello
value: world

如果单项数据 中包含空格, 则需把单项数据用双引号 " 括起来:

$ cat temp.sh
#!/bin/bash
for username in "miyan" "rosie cui" "mitre chen" "abby wang"; do
    echo user: $username
done

$ ./temp.sh
user: miyan
user: rosie cui
user: mitre chen
user: abby wang

我们可以把 "miyan" "rosie cui" "mitre chen" "abby wang" 赋值给一个变量 list ,
然后从 list 中遍历:

$ cat temp.sh
#!/bin/bash
IFS=$'\n'
# echo -e 可以把 \n 转成换行
list=$(echo -e "miyan\nrosie cui\nmitre chen\nabby wang")
for username in $list; do
    echo user: $username
done
$ ./temp.sh
user: miyan
user: rosie cui
user: mitre chen
user: abby wang

注意:
环境变量 IFS (internal field separator, 内部字段分隔符) 默认会把下列字符当成 字段分隔符:

  1. 空格
  2. 制表符
  3. 换行符

所以, 在上面的示例中, 我们先把 IFS 修改为 换行符, 这样 for 在分割字符串, 只会把每个换行符前当成一次迭代, 而不会把带空格 的字符串分割成多个迭代.

1.1 从命令读取值

从 命令 $(command) 中读取值赋予 for 命令:

$ cat namefile
mitre chen
rosie cui

$ cat temp.sh
#!/bin/bash
IFS=$'\n'
for name in $(cat namefile); do
    echo name: $name
done

$ ./temp.sh
name: mitre chen
name: rosie cui

1.2 用通配符读取目录

for-in 结构中, 在 in 后面使用统配符.

很简单, 看示例:

$ cat temp.sh
#!/bin/bash
for file in /home/miyan/test/*; do
    if [ -d "$file" ]; then
        echo "$file is a directory"
    elif [ -f "$file" ]; then
        echo "$file is a file"
    fi
done

$ ./temp.sh
/home/miyan/test/811.log is a file
/home/miyan/test/awk is a directory
/home/miyan/test/namefile is a file
/home/miyan/test/symbolicFile2 is a file
/home/miyan/test/temp.sh is a file

1.3 for-in 遍历数字范围

遍历 全数范围(full number range), 示例:

$ cat temp.sh
#!/bin/bash
for i in {1..5}; do
    echo "value: $i"
done
echo "======="
for i in {01..05}; do
    echo "value: $i"
done

$ ./temp.sh
value: 1
value: 2
value: 3
value: 4
value: 5
=======
value: 01
value: 02
value: 03
value: 04
value: 05

for-in 遍历数字范围还是挺智能的, 能区分开 {1..5}{01..05}.

for-in 跳跃遍历数字范围:

$ cat temp.sh
#!/bin/bash
# 遍历1..50, 间隔是10
for i in {1..50..10}; do
    echo "value: $i"
done

$ ./temp.sh
value: 1
value: 11
value: 21
value: 31
value: 41

2 C 语言风格 for 命令

bash 中 C 语言风格的 for 循环 的格式:

for (( variable assignment; condition; iteration process ))

还记得双括号(())if-then 中处理数学运算吗?

C 语言风格的 for 对于高级语言程序员来说, 很好理解:

$ cat temp.sh
#!/bin/bash
for (( i = 0; i<5; i++)); do
    echo "value: $i"
done

$ ./temp.sh
value: 0
value: 1
value: 2
value: 3
value: 4

3 while 命令

while 命令的格式:

while condition
do
    commands
done

while 这里的 条件测试if-then 中的 条件测试 格式一模一样. condition 可以使用任何的普通的 bash shell 命令, 或者使用 test 命令进行条件测试.

示例:

$ cat temp.sh
#!/bin/bash
var=3
# 条件测试, 注意空格
while [ $var -gt 0 ]; do
    echo $var
    var=$[$var-1]
done
echo "=============="
var=3
# 双括号(()) 处理高级数学表达式
while (( $var > 0)); do
    echo $var
    var=$[$var-1]
done

$ ./temp.sh
3
2
1
==============
3
2
1

还记得吗?

  1. 方括号 [ ] 是 bash 用于替换 test 条件测试 的.
  2. $[expression] 是 bash 用于替换 expr 进行数学表达式计算的.
  3. (()) 处理数学运算

4 until 命令

只有 条件测试 的 退出状态码 不为 0, until 才会执行循环中的命令; 退出状态码 为 0, 循环就结束了.

until 命令格式:

until condition
do
    commands
done

until 命令示例:

$ cat temp.sh
#!/bin/bash
var=3
until [ $var -le 0 ]; do
    echo $var
    var=$[$var-1]
done

$ ./temp.sh
3
2
1

5 控制循环

一旦进入了循环, 必须等到循环结束? 不是这样的, 我们可以通过 break 跳出循环, 也可以通过 continue 跳过单个循环.

5.1 break 命令

直接看示例:

cat temp.sh
#!/bin/bash
for i in {1..10}; do
    if [ $i -gt 3 ]; then
        break;
    fi
    echo $i
done

$ ./temp.sh
1
2
3

当遍历到 4 时, 大于 3, break 跳出循环.

break 完整的写法时 break n, 其中 n 指定了要跳出的 循环层级, 默认情况下, n=1 表示跳出的是当前循环.

如果想要跳出 外层循环, 必须 令 n=2 :

$ cat temp.sh
#!/bin/bash
for i in {1..10}; do
    for (( j=0; j<10; j++ )); do
        if [ $j -gt 3 ]; then
            break 2;
         fi
         echo "i=$i, j=$j"
     done
done

$ ./temp.sh
i=1, j=0
i=1, j=1
i=1, j=2
i=1, j=3

5.2 continue 命令

continuebreak 的用法相似, 直接看个示例:

$ cat temp.sh
#!/bin/bash
for i in {1..5}; do
    if [ $i -eq 3 ]; then
        continue
    fi
    echo "$i"
done

$ ./temp.sh
1
2
4
5

break 一样, continue 的完整写法时 continue n, 其中 n 指定了要跳过的 循环层级, 默认情况下, n=1 表示跳过的是当前循环一次迭代.

6 处理循环的输出

在 shell 脚本种, 可以对循环的输出 使用 管道重定向, 通过在 done 命令后面添加一个处理命令实现.

for 命令中使用 输出重定向 把 循环的输出 重定向 到文件中:

$ cat temp.sh
#!/bin/bash
for i in {1..5}; do
    if (( $i % 2 == 0)); then
        echo "$i even"
    else
        echo "$i odd"
    fi
done > temp.log

$ ./temp.sh
$ cat temp.log
1 odd
2 even
3 odd
4 even
5 odd

for 命令中使用 管道, 把 循环的输出 通过 管道 传给另一个命令:

$ cat temp.sh
#!/bin/bash
for i in {1..5}; do
    if (( $i % 2 == 0)); then
        echo "$i even"
    else
        echo "$i odd"
    fi
done | sort -r

$ ./temp.sh
5 odd
4 even
3 odd
2 even
1 odd

Reference

[1]. Linux命令行与shell脚本编程大全(第三版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值