• shell脚本循环嵌套


    嵌套循环

    在循环语句内使用任意类型的命令,包括其他循环命令,叫做嵌套循环。因为是在迭代中迭代,需要注意变量的使用以及程序的效率问题。

    下面举一个for循环嵌套for循环的例子:

    wangsx@SC-201708020022:~/tmp$ cat test14
    #!/bin/bash
    # nesting for loops
    
    for (( a = 1; a <= 3; a++ ))
    do
            echo "Starting loop $a:"
            for (( b = 1; b <= 3; b++ ))
            do
                    echo "    Inside loop: $b"
            done
    done
    
    wangsx@SC-201708020022:~/tmp$ . test14
    Starting loop 1:
        Inside loop: 1
        Inside loop: 2
        Inside loop: 3
    Starting loop 2:
        Inside loop: 1
        Inside loop: 2
        Inside loop: 3
    Starting loop 3:
        Inside loop: 1
        Inside loop: 2
        Inside loop: 3
    

    shell能够自动识别匹配的dodone字符。这种模式很常见,比如通常的小括号(())、中括号、花括号匹配等等。它们的本质都是字符匹配。

    在混用循环命令时也一样,比如在while循环中内嵌一个for循环:

    wangsx@SC-201708020022:~/tmp$ cat test15
    #!/bin/bash
    # placing a for loop inside a while loop
    
    var1=5
    
    while [ $var1 -ge 0 ]
    do
            echo "Outer loop: $var1"
            for (( var2 = 1; $var2 < 3; var2++))
            do
                    var3=$[ $var1 * $var2 ]
                    echo "  Inner loop: $var1 * $var2 = $var3"
            done
            var1=$[ $var1 - 1 ]
    done
    
    wangsx@SC-201708020022:~/tmp$ . test15
    Outer loop: 5
      Inner loop: 5 * 1 = 5
      Inner loop: 5 * 2 = 10
    Outer loop: 4
      Inner loop: 4 * 1 = 4
      Inner loop: 4 * 2 = 8
    Outer loop: 3
      Inner loop: 3 * 1 = 3
      Inner loop: 3 * 2 = 6
    Outer loop: 2
      Inner loop: 2 * 1 = 2
      Inner loop: 2 * 2 = 4
    Outer loop: 1
      Inner loop: 1 * 1 = 1
      Inner loop: 1 * 2 = 2
    Outer loop: 0
      Inner loop: 0 * 1 = 0
      Inner loop: 0 * 2 = 0
    

    如果想要挑战脑力,可以混用untilwhile循环。

    wangsx@SC-201708020022:~/tmp$ cat test16
    #!/bin/bash
    # using until and while loop
    
    var1=3
    
    until [ $var1 -eq 0 ]
    do
            echo "Outer loop: $var1"
            var2=1
            while [ $var2 -lt 5 ]
            do
                    var3=$(echo "scale=4; $var1 / $var2" | bc)
                    echo "  Inner loop: $var1 / $var2 = $var3"
                    var2=$[ $var2 + 1 ]
            done
            var1=$[ $var1 - 1 ]
    done
    
    wangsx@SC-201708020022:~/tmp$ . test16
    Outer loop: 3
      Inner loop: 3 / 1 = 3.0000
      Inner loop: 3 / 2 = 1.5000
      Inner loop: 3 / 3 = 1.0000
      Inner loop: 3 / 4 = .7500
    Outer loop: 2
      Inner loop: 2 / 1 = 2.0000
      Inner loop: 2 / 2 = 1.0000
      Inner loop: 2 / 3 = .6666
      Inner loop: 2 / 4 = .5000
    Outer loop: 1
      Inner loop: 1 / 1 = 1.0000
      Inner loop: 1 / 2 = .5000
      Inner loop: 1 / 3 = .3333
      Inner loop: 1 / 4 = .2500
    

    外部的until循环以值3开始,并继续执行到值等于0。内部while循环以值1开始一直执行,只要值小于5。需要注意循环条件的设置,我跑的几次都没写完整,然后无限循环只好重开终端。

    控制循环

    之前的学的命令已经可以让我们写循环程序了,设定好以后等待命令开始执行和等待循环结束。但是很多情况下,在循环中我们设定的某个(多个)变量达到某种条件时,我们就想要停止循环,然后运行循环下面的命令。这时候我们需要用到breakcontinue命令来帮我们控制住循环。

    这两个命令在其他语言中基本都时关键字,特别是C,用法差不多。我也就不具体介绍了,只点出它们的功能。

    break

    在shell执行break命令时,它会尝试跳出当前正在执行的循环。

    在处理多个循环时,break命令会自动终止你所在的最内层循环。

    break命令接受单个命令行参数值:

    ​ break n

    ​ 其中n制订了要跳出的循环层级(层数)

    continue

    continue命令可以提前终止某次循环的命令,但并不会完全终止整个循环。可以在循环内部设置shell不执行命令的条件。

    也就是说使用continue命令时,它会自动跳过本次循环中接下来的运行步骤,跳转到下一次循环。但注意不是跳出,跳出时break的功能。

    同样的可以使用continue n n制定要继续执行哪一级循环

    处理循环的输出

    在shell脚本中,我们可以对循环的输出使用管道或进行重定向。这是通过在done命令之后添加一个处理命令来实现的。

    wangsx@SC-201708020022:~/tmp$ cat test
    #!/bin/bash
    for file in /home/*
    do
            if [ -d "$file" ]
            then
                    echo "$file is a directory"
            else
                    echo "$file is a file"
            fi
    done > output.txt
    wangsx@SC-201708020022:~/tmp$ cat output.txt
    /home/wangsx is a directory
    

    shell将for命令的结果重定向到文件output.txt中,而不是显示在屏幕上。

    实例

    下面两个例子演示如何用简单循环来处理数据。

    查找可执行文件

    Linux运行程序时通过环境变量$PATH提供的目录搜索可执行文件。如果徒手找的话,比较费时间,我们可以写个脚本来搞定它。

    wangsx@SC-201708020022:~$ cat test25
    #!/bin/bash
    # finding files in the PATH
    
    IFS=:
    for folder in $PATH
    do
            echo "$folder:"
            for file in $folder/*
            do
                    if [ -x $file ]
                    then
                            echo "  $file"
                    fi
            done
    done
    
    # 输出结果太多,我就不拷贝结果了
    

    先设定IFS分隔符以便于能正确分隔目录,然后将目录存放在$folder中,用for循环来迭代特定的目录中所有文件,然后用if-then命令检查文件的可执行权限。

    Linux有一个tree工具,非常方便输出目录结构,推荐使用下。

    创建多个用户账号

    如果你是管理员,需要创建大量账号时。不必每次都有useradd命令添加用户。将用户信息存放在指定文件,然后用脚本进行处理就可以了。

    用户信息的格式如下:

    userid, user name
    

    第一个是你为用户选择的id,第二个是用户的全名。这是csv文件格式。

    为了能够读取它,我们使用以下命令:

    while IFS=',' read -r userid name
    

    read命令会自动获取.csv文本文件的下一行内容,所以不用再写一个循环来处理。当read命令返回FALSE时(也就是读完了),while命令就会退出。

    为了把数据从文件导向while命令,只要再while命令尾部加一个重定向符号。

    处理过程写成脚本如下:

    #!/bin/bash
    # process new user accounts
    
    input="users.csv"
    while IFS=',', read -r userid name
    do
        echo "adding $userid"
        useradd -c "$name" -m $userid
    done < "$input"


    作者:王诗翔
    链接:https://www.jianshu.com/p/8b09c76f5f75
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    django 基础2 Djanos三件套+form三要素+ORM
    django 基础 1 web框架原理
    pg_dump: [archiver (db)] query failed: ERROR: out of shared memory HINT: You might need to increase max_locks_per_transaction. IN ACCESS SHARE MODE
    Ubuntu 16.04——配置Nginx及Https服务
    使用Nginx设置基本HTTP身份验证
    关于报错 :MySQLdb._exceptions.OperationalError: (2026, 'SSL connection error: SSL_CTX_set_tmp_dh failed')
    redis报错 Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check
    Sublime插件Emmet的安装及Tab补全代码问题解决
    Python编程基础[函数和面向对象](三)
    Python编程基础变量赋值,字典,切片,[条件语句if 循环语句 for,while](二)
  • 原文地址:https://www.cnblogs.com/weifeng1463/p/9182794.html
Copyright © 2020-2023  润新知