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

文章目录


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


shell循环语句for命令

bash shellfor 命令的基本格式:

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

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

until命令和 while 命令工作的方式完全相反。只有测试命令的退出状态码不为 0bash 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默认是跳出当前层的循环,而与其他大多数语言不同的是shellbreak命令还支持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会直接结束循环。在whileuntil循环中同样支持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

也可以在 whileuntil 循环中使用 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

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


相关推荐
娅娅梨15 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
汤米粥20 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾23 分钟前
EasyExcel使用
java·开发语言·excel
拾荒的小海螺30 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
java—大象1 小时前
基于java+springboot+layui的流浪动物交流信息平台设计实现
java·开发语言·spring boot·layui·课程设计
yyqzjw1 小时前
【qt】控件篇(Enable|geometry)
开发语言·qt
csdn_kike1 小时前
QT Unknown module(s) in QT 以及maintenance tool的更详细用法(qt6.6.0)
开发语言·qt