更多的结构化命令

  前面介绍了if和case语句,这一节我们了解for、while和until语句

1、for命令

  对命令进行重复执行,是编程思想中的常见方式。

  bash shell提供了for命令,来重复执行一组命令:

    for var in list 

    do

      commands

    done

  参数list用于提供一些用于迭代的值。

  1.1、读取列表中的值

    给变量test轮流复制;

#!/bin/bash
#basic for command
for test in Alabama Alaska Alaska Arizona Arkansas California Colorado
do
    echo The next state is $test
done

    最后一个值,colorado赋值完成以后,会继续向下运行脚本程序

#!/bin/bash
#testing the for variable after the looping

for test in Alabama Alaska Ariziona Arkansas California Colorado
do 
    echo "The next state is $test"
done
echo "The last state we visited was $test"
test=Connecticut
ehco "Wait,now we're visiting $test"

  1.2、读取列表中的复杂值

    事情不会那么简单,以下实例说明一个麻烦:

#!/bin/bash
#another example of how not to use the fo command

for test in I don't know if this'll work
do 
    echo "word:$test"
done

    其中 't know if this' 被识别为了一个字符串,同时赋值给了test

    解决方法:1、使用转意字符;2、使用双引号来定义使用的单引号的值;

#!/bin/bash
#another example of how not to use the for command
for test in I don't know if "this'll" work
do 
    echo "word:$test"
done

    所以,我们需要技术,for循环中每个值都是用空格隔开的。我们就需要用双引号引起来;

#!/bin/bash
#an example of how to properly define values

for test in Nevada "New Hampshire" "New Mexico" "New York"
do
    echo "Now going to $test"
done

  1.3、从变量读取列表

    我们会将列表存储于变量中,让for语句从变量中读取数据;

#!/bin/bash
#using a variable to hold the list

list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"

for state in $list
do
    echo "Have you ever visited $state?"
done

  1.4、读取命令中的值

    可以使用反引号来获取命令执行结果,赋值给变量,再对变量进行遍历;

#!/bin/bash
#reading values from a file 

file="states"

for state in `cat $file`
do
    echo "Visit beautiful $state"
done

    这里注意,states文件中的内容,每一行包含一个转态,用空格隔开。

  1.5、改变字段分隔符

    默认使用空格做分隔符。但是根据IFS--内部字段分割符包括三个:空格、制表符、换行符。

    如何选择其他的符号作为分隔符呢,或者是同时使用多个符号做分隔符呢?

#!/bin/bash
#reading values from a file

file="states"

IFS=$`
`  #IFS值来定义分隔符,可以通过该命令,来改变分隔符;
 表示以回车为分隔符
for state in `cat $file`
do
    echo "Visit beautiful $state"
done

    在工作中对于分隔符的定义方法,先保存原来的分隔符,等在使用时候恢复过来即可

IFS.OLD=$IFS
IFS=$`
`
<user teh new IFS value in code>
IFS=$IFS.OLD

    如果想指定多个分隔符

IFS=$`
`:;"  #这里使用了回车、冒号、分号、双引号同时作为分隔符

  1.6、使用通配符读取目录

    文件通配符匹配目录

#!/bin/bash
#iterate through all the files in a directory

for file in /home/rich/test/*
do
    if [ -d "$file" ]  #判断文件是否为目录
    then
        echo "$file is a directory"
    elif [ -f "$file" ]  #判断是否为普通文件
    then
        echo "$file is a file"
    fi
done

    可以出了使用通配符,还可以结合列表

#!/bin/bash
#iterating through multiple directories

for file in /home/rich/.b* /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

2、C式的for命令

  在C语言中,for循环通常定义一个变量,该变量在每次迭代过程中自动改变值。通常程序员将该变量用做计数器,每次迭代计数器要么增加一个,要么减少一个。bash的for命令也能提供这种功能。

  2.1、C语言中的for命令

    在C语言的循环中,for一直要保持true才能继续运行,直到false,则循环结束

for (i = 0; i < 10; i++)
{
    printf("The next number is %d
", i);    
}

    i作为计数器。一直累加,当不符合条件时循环结束;

    bash shell可以使用这种思路,来编写自己的for循环脚本语句;

格式:for (( variable assignment ; condition ; iteration process ))
for (( a=1; a<10; a++ ))

    注意,有几项是不遵循bash shell的for方法:1、变量的复制可以包含空格;2、条件中的变量不以$符号做前缀;3、迭代处理式不适用expr命令格式;

    在shell脚本中,使用C式的程序需要谨慎;

#!/bin/bash
#testing the C-style for loop

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

  2.2、使用多个变量

    C式的shell只能在for循环中定义一个条件,是具有局限性的;

#!/bin/bash
#multiple variables

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

3、while命令

  while命令像是if-then和for的结合体。while是容许要定义测试的命令,只要定义的测试命令返回值为0,就循环一组命令。它在每次迭代开始时检查测试命令,测试命令返回值为非零,while则终止执行命令集;

  3.1、while基本格式

    while命令的格式:

      while test command

      do 

        other commands

      done

    在while语句中,test与if-then语句中的定义格式一样;while的关键是,在运行other commands后一点要改变test转态,否则就会进入死循环;

#!/bin/bash
#while command test

var1=10
while [ $var1 -gt 0 ]  #比较var1值与0的大小
do
    echo $var1
    var1=$[ $var1 - 1 ]  #每次循环完成都要对var1参数减1才行
done

  3.2、使用多条测试命令

    while语句容许定义多条test命令。只有最后一条test命令的状态才决定循环何时停止;

#!/bin/bash
# testing a multicommand while loop

var1=10

while echo $var1
    [ $var1 -ge 0 ]
do
    echo "This is inside the loop"
    var1=$[ $var1 - 1 ]
done

    上面的这个脚本中while的测试语句有两条,ehco $var1和[ $var1 -ge 0 ],所以,最后是否运行do-done中的命令,取决于 [ $var1 -ge 0 ] 这条命令的测试结果

4、until命令

  until命令刚好和while命令相反。定义一个测试语句,如果返回为非0结果,则运行do-done中的语句,如果是0结果,则不运行do-done中的语句;

  until命令的格式:

    until test commands

    do

      other commands

    done

  与while类似,可以使用多条测试语句,但是依然只有最后条测试语句才生效;

#!/bin/bash
# using the until command

var1=100

until [ $var1 -eq 0 ]
do 
    echo $var1
    var1=$[ $var1 - 25 ]
done

  一旦结果变为0,则运行结果停止。

#!/bin/bash
#using the until command

var1=100

until echo $var1
    [ $var1 -eq 0 ]
do
    echo Inside the loop: $var1
    var1=$[ $var1 -25 ]
done

5、嵌套循环

  一条循环语句可以在循环中使用任何类型的命令,包括其他循环的命令,就是嵌套循环。

  一个for循环中嵌套另一个for循环实例:

#!/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

  for循环放在while循环内:

#!/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

  until和while循环也是可以结合起来:

#!/bin/bash
# using until and while loops

var1=3

until [ $var1 -eq 0 ]  #从3开始,只要不等于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 ]  #执行完一次,我们需要对var1 - 1 不能一直循环下去
done

6、文件数据的循环

  迭代存储在文件内部的项,需要结合两种介绍过的技术:1、使用嵌套循环;2、更改环境变量IFS;

  通过更改环境变量IFS,可以迫使for命令将文件中的每行作为单独的一项来处理,即使数据含有空格。提取了文件中的个别行之后,您可能还需要再循环已提取其宝行的数据;

  以/etc/passwd文件中处理数据为例:

#!/bin/bash
# changing the IFS value
IFS.OLD=$IFS
IFS=$`
`
for entry in `cat /etc/passwd`
do
    echo "Values in $entry -"
    IFS=:
    for value in $entry
    do
        echo "$value"
    done
done

  先取出每行,在再每行上以:为分隔符在取一遍数值;

7、控制循环

  我们可以通过命令控制循环内部发生的事情。1、break;2、continue;

  这两条命令用于控制循环操作;

  7.1、break

    在循环的过程中,跳出循环的一种简单方法。可以使用break退出任何类型的循环;

    1、跳出单循环

#!/bin/bash
# breaking out of a for loop

for var1 in 1 2 3 4 5 6 7 8 9 10
do 
    if [ $var1 -eq 5 ]
    then
        break 
    fi
    echo "Iteration number: $var1"
done
echo "The for loop is completed"

    for循环通常迭代列表中指定的所有值。然而,当if-then条件满足,shell执行break命令就能终止for循环;这种方式同样适用于while和until循环;

#!/bin/bash
# breaking out of a while loop

var1=1

while [ $var1 -lt 10 ]
do
    if [ $var1 -eq 5 ]
    then
        break
    fi
    echo "Iteration: $var1"
    var1=$[ $var1 + 1 ]
done
echo "The while loop is completed"

    2、跳出内循环

    使用多循环时break命令自动终止您所在的最里面的内部循环;

#!/bin/bash
# breaking out of an inner loop

for (( a = 1; a < 4; a++ ))
do
    echo "Outer loop: $a"
    for (( b = 1; b < 100; b++ ))
    do
        if [ $b -eq 5 ]
        then
            break
        fi
        echo " Inner loop: $b"
    done
done

    3、跳出外循环

    可能有时处于内循环单需要停止外循环。break命令宝行单独的命令执行参数;

#!/bin/bash
# breaking out of an outer loop

for (( a = 1; a < 4; a++ ))
do
    echo "Outer loop: $a"
    for (( b = 1; b < 100; b++ ))
    do 
        if [ $b -gt 4 ]
        then
            break 2
        fi
        echo " Inner loop: $b"
    done
done

    这里 2 数据表示循环级别,当前所处的 循环级别为 1 ;向外一次加。就是 2级循环;

  7.2、continue

    不终止循环,只是跳过这一个循环值,后面的依然继续运行;

    for循环中使用continue

#!/bin/bash
# using the contnue command

for (( var1 = 1; var1 < 15; var1++ ))
do
    if [ $var -gt 5 ] && [ $var1 -lt 10 ]
    then
        continue
    fi
    echo "Iteration number: $var1"
done

    var1值大于5小于10的话,就被continue跳过了;

    在until和while中使用continue要特别谨慎,不能在键值添加的时候跳过这个添加值的过程;

#!/bin/bash
# improperly using the continue command in a while loop

var1=0
while echo "while iteration: $var1"
        [ $var1 -lt 15 ]
do
    if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
    then 
        continue
    fi
    echo "Inside iteration number: $var1"
    var1=$[ $var1 + 1 ]
done

    在大于5小于10的时候跳过了var1自加的过程,则时候就进入了死循环!!!这一点一定要注意;

    同样的,continue命令可以使用 continue n 来指定停止的循环级别;

#!/bin/bash
# continuing an outer loop

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 $a * $b is $var3"
    done
done

8、处理循环输出

  最后,在shell循环中,使用管道和重定向符号处理输出结果;

for file in /home/rich/*
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif
        echo "$file is a file"
    fi
done > output.txt

  可以将脚本内容重定向到output.txt中,而不是输出到屏幕

#!/bin/bash
# redirecting the for output to a file

for (( a = 1; a < 10; a++ ))
do
    echo "The number is $a"
done > test23.txt
echo "The command is finished."

  同样的技术,也可以用于将循环的输出管道传送给其他命令:

#!/bin/bash
# piping a loop to another command

for state in "North Dakota" Connecticut Illinois Alabama Tennessee
do 
    echo "$state is the next place to go"
done | sort
echo "This completes our travels"

  for输出的结果传送给sort来进行操作;

原文地址:https://www.cnblogs.com/BurnovBlog/p/10783575.html