14.bash shell中的for/while/until循环

文章目录


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


shell循环语句for命令

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

sh 复制代码
for var in list
do
    commands
done

list参数中,需要提供迭代中要用到的一系列值。指定列表中值的方法:

读取列表中的值

sh 复制代码
#!/bin/bash
for v in a b c; do
        echo "The Text is $v"
done

# The Text is a
# The Text is b
# The Text is c

读取列表中的复杂值

当列表中包含单引号时会导致迭代出错:

sh 复制代码
#!/bin/bash
for v in I can't argee that's right ; do
        echo "The word is $v"
done

# The word is I
# The word is cant argee thats
# The word is right

可以看到因为受单引号的影响并没有按word by word输出。解决办法有两个,

  • 对单引号进行转义
  • 使用双引号包围
sh 复制代码
#!/bin/bash
for v in I can\'t argee "that's" right ; do
        echo "The word is $v"
done

# The word is I
# The word is can't
# The word is argee
# The word is that's
# The word is right

for 命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。

sh 复制代码
#!/bin/bash
for v in a "b c" ; do
        echo "The word is $v"
done

# The word is a
# The word is b c

从变量读取列表

将一系列值都集中存储在了一个变量中,然后需要遍历变量中的整个列表。

sh 复制代码
#!/bin/bash
ll="a b c"
ll=$ll" dd"
for s in $ll
do
    echo "char $s"
done 

# char a
# char b
# char c
# char dd

迭代数组

前面介绍过数组的定义,这里使用for循环在bash shell中使用array的方式如下:

sh 复制代码
#!/bin/bash

arr=(1 2 3)
for i in ${arr[@]}; do
    echo $i
done

# 1
# 2
# 3

${array[@]}是取数组中的所有值。

从命令读取值

生成列表中所需值的另外一个途径就是使用命令的输出。

sh 复制代码
#!/bin/bash

# content of file
# a bbb
# b
# cc
# ddd

file=file
for v in $(cat $file)
do
    echo "value from file $v"
done

# value from file a
# value from file bbb
# value from file b
# value from file cc
# value from file ddd

设置for命令分割符 ,bash shell中默认的分割符是空格/制表符/换行符,这是由特殊的环境变量 IFS(internal field separator),也被称为内部字段分隔符。

要解决这个问题,可以在shell脚本中临时更改 IFS 环境变量的值来限制被bash shell当作字段分隔符的字符。例如,如果修改 IFS 的值,使其只能识别换行符,那就必须这么做:

sh 复制代码
IFS=$'\n'
sh 复制代码
#!/bin/bash

# content of file
# a bbb
# b
# cc
# ddd

IFS=$'\n'
file=file
for v in $(cat $file)
do
    echo "value from file $v"
done

# value from file a bbb
# value from file b
# value from file cc
# value from file ddd

如果要指定多个 IFS 字符,只要将它们在赋值行串起来就行。

sh 复制代码
IFS=$'\n':;"

用通配符读取目录

可以用 for 命令来自动遍历目录中的文件。进行此操作时,必须在文件名或路径名中

使用通配符。它会强制shell使用文件扩展匹配。文件扩展匹配是生成匹配指定通配符的文件名或

路径名的过程。

sh 复制代码
#!/bin/bash

for file in /home/rob/* /home/rich/badtest
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif [ -f "$file" ]
    then
        echo "$file is a file"
    else
        echo "$file doesn't exist"
    fi
done

# /home/rob/模板 is a directory
# /home/rob/file is a file
# /home/rob/test1 is a file
# /home/rob/test2 is a file
# /home/rob/test.sh is a file
# /home/rich/badtest doesn't exist

C语言风格的shell for循环

shell还可以支持类似C语言的for循环,变量和等号之间可以有空格,访问变量的值不需要$符号。但这会造成shell程序编写人员的困惑,减少使用。

sh 复制代码
#!\bin\bash

for (( i=1; i <= 5; i++))
do
    echo "The next number is $i" 
done


# The next number is 1
# The next number is 2
# The next number is 3
# The next number is 4
# The next number is 5

shell循环while命令

while命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码 0 。它会在每次迭代的一开始测试 test 命令。在 test 命令返回非零退出状态码时, while 命令会停止执行那组命令。

while 命令格式

sh 复制代码
while test command
do
    other commands
done

while 命令中定义的 test command 和 if-then 语句中的格式一模一样。

最常见的 test command 的用法是用方括号来检查循环命令中用到的shell变量的值。

sh 复制代码
#!/bin/bash

nu=5
while [ $nu -gt 0 ]
do
    echo "nu: $nu"
    nu=$[ $nu - 1 ]
done

# nu: 5
# nu: 4
# nu: 3
# nu: 2
# nu: 1

while 命令允许在 while 语句行定义多个测试命令。只有最后一个测试命令的退出状态码

会被用来决定什么时候结束循环。

sh 复制代码
#!/bin/bash

nu=5
while echo $nu
    [ $nu -gt 0 ]
do
    echo "nu: $nu"
    nu=$[ $nu - 1 ]
done

# 5
# nu: 5
# 4
# nu: 4
# 3
# nu: 3
# 2
# nu: 2
# 1
# nu: 1
# 0

第一个测试简单地显示了 var1 变量的当前值。第二个测试用方括号来判断 var1 变量的值。

在循环内部, echo 语句会显示一条简单的消息,说明循环被执行了。运行本例时输出

以0结束,说明执行了[ $nu -gt 0 ]之前的echo $nu语句。

shell 循环的until命令

while命令中,只要定义的测试命令返回的是退出状态码 0,while就会一直执行,在 test 命令返回非零退出状态码时, while命令会停止执行那组命令。

sh 复制代码
while test command
do
    other commands
done

until命令和 while 命令工作的方式完全相反。只有测试命令的退出状态码不为 0 ,bash shell才会执行循环中列出的命令。

sh 复制代码
until test commands
do
    other commands
done

until命令的一个实例:

sh 复制代码
#!/bin/bash
nu=8
until [ $nu -eq 0 ]
do 
    echo $nu
    nu=$[ $nu - 2 ]
done

# 8
# 6
# 4
# 2

和 while 命令类似,你可以在 until 命令语句中放入多个测试命令。只有最后一个命令的退

出状态码决定了bash shell是否执行已定义的 other commands 。

sh 复制代码
#!/bin/bash
nu=8
until [ $nu -eq 0 ]
      echo $nu
do
    echo $nu
    nu=$[ $nu - 2 ]
done

shell会执行指定的多个测试命令,只有在最后一个命令成立时停止。

shell循环跳出的break/continue命令

break命令

当满足某个条件时,有时会希望终止循环,shell和大多数变成语言一样支持break/continue命令,其使用方法:

sh 复制代码
#!/bin/bash
for (( a=1; a<=10; a++ ))
do
    echo "value a $a"
    for((b=1; b<=10; b++ ))
    do
        echo "  value b $b"
        if [ $b -eq 4 ]; then
            echo "  break"
            break 2
        fi
    done
done

# break
# value 1
# value 2
# value 3
# value 4

值得注意的是break默认是跳出当前层的循环,而与其他大多数语言不同的是shell的break命令还支持break n参数,n表示跳出几层循环,默认为1。

sh 复制代码
#!/bin/bash
for (( a=1; a<=10; a++ ))
do
    echo "value a $a"
    for((b=1; b<=10; b++ ))
    do
        echo "  value b $b"
        if [ $b -eq 4 ]; then
            echo "  break"
            break 2
        fi
    done
done

# value a 1
#   value b 1
#   value b 2
#   value b 3
#   value b 4
#   break

如上,break会直接结束循环。在while和until循环中同样支持break命令。

continue命令

continue命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。

sh 复制代码
#!/bin/bash
for (( v=1; v<=10; v++ ))
do
    if [ $v -gt 5 ] && [ $v -lt 8 ]; then
        continue
    fi
    echo "Iteration: $v"
done

# Iteration: 1
# Iteration: 2
# Iteration: 3
# Iteration: 4
# Iteration: 5
# Iteration: 8
# Iteration: 9
# Iteration: 10

也可以在 while 和 until 循环中使用 continue 命令,但要特别小心。记住,当shell执行continue 命令时,它会跳过剩余的命令。

和 break 命令一样, continue 命令也允许通过命令行参数指定要继续执行哪一级循环continue n。

sh 复制代码
#!/bin/bash
for (( a = 1; a <= 5; a++ ))
do
    echo "Iteration $a:"
    for (( b = 1; b < 3; b++ ))
    do
        if [ $a -gt 2 ] && [ $a -lt 4 ]; then
            continue 2
        fi
    var3=$[ $a * $b ]
    echo "    The result of of $a * $b is $var3"
    done
done

# Iteration 1:
#     The result of of 1 * 1 is 1
#     The result of of 1 * 2 is 2
# Iteration 2:
#     The result of of 2 * 1 is 2
#     The result of of 2 * 2 is 4
# Iteration 3:
# Iteration 4:
#     The result of of 4 * 1 is 4
#     The result of of 4 * 2 is 8
# Iteration 5:
#     The result of of 5 * 1 is 5
#     The result of of 5 * 2 is 10

trick

在上面的命令中使用重定向,可以将循环中命令的结果保存到文件中。

sh 复制代码
#!/bin/bash
for (( a = 1; a <= 5; a++ ))
do
    echo "Iteration $a:"
    for (( b = 1; b < 3; b++ ))
    do
        if [ $a -gt 2 ] && [ $a -lt 4 ]; then
            continue 2
        fi
    var3=$[ $a * $b ]
    echo "    The result of of $a * $b is $var3"
    done
done > out.txt

还可以使用管道命令将循环的结果传递给别的命令,

sh 复制代码
#!/bin/bash

for (( a = 1; a <= 5; a++ ))
do
    echo "Iteration $a:"
    for (( b = 1; b < 3; b++ ))
    do
        if [ $a -gt 2 ] && [ $a -lt 4 ]; then
            continue 2
        fi
    var3=$[ $a * $b ]
    echo "    The result of of $a * $b is $var3"
    done
done | sort

欢迎访问个人网络日志🌹🌹知行空间🌹🌹


相关推荐
一水鉴天7 小时前
映射、哈希表与哈斯图:计算机科学的三种基线 20261003(元宝)
开发语言·人工智能
Frank_refuel7 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
Wang's Blog8 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
2601_962071579 小时前
类变量和全局变量的查找路径有什么区别?
开发语言·python
\光辉岁月/10 小时前
5.java-数组
java·开发语言
Java后端的Ai之路10 小时前
Python进阶探索29_eval内置函数
开发语言·python·探索·eval·内置函数
谢亮_vipxieliang10 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
时间的拾荒人10 小时前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
郑州光合科技余经理10 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_9620715710 小时前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm