shell脚本学习四(结构化命令for、while、util)

shell脚本学习四(结构化命令for、while、util)

Scroll Down

for 命令:

              for   var   in  list 

              do

                       commands

              done

 

$user 变量保持了其值,也允许我们修改它的值,并在 for 命令循环之外跟其他变量一样使用 

 从命令读取值:

       

      

       

一个特殊的环境变量 IFS,叫做内部字段分隔符( internal  field  separator ),IFS 环境变量定义了 bash shell 用作字段分隔符的一系列字符,默认情况下,bash shell 会将 空格 、 制表符、 换行符 当做字段分隔符。当然,可以通过在 shell 脚本中临时修改 IFS 环境变量的值来限制被 bash shell 当做字段分隔符的字符。

     例如:如果你想修改 IFS 的值,使其只能识别换行符,则   IFS = $ '\n'

在处理代码量较大的脚本时。可能在一个地方需要修改 IFS 的值,然后忽略这次修改,在脚本其他地方继续沿用 IFS 默认值,一个可参考的安全实践是在改变 IFS 之前保存原来的 IFS 值,之后在恢复它,可以通过

              IFS.OLD=$ IFS

              IFS=$'\n'

              <在代码中使用新的 IFS 值>

              IFS=$IFS.OLD

              这就保证了在脚本的后续操作中使用的是默认的 IFS 值 

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

               IFS=$'\n':;"

 while 命令:

     格式为   while   test command

                   do 

                         other  cammands

                    done

  while 命令允许你在 while 语句行定义多个测试命令,只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环。

util 命令和 while 命令刚好相反,只有测试命令的退出状态码不为 0,bash shell 才会执行循环中列出的命令,一点测试命令返回了退出状态码 0,循环就结束了(和 while 一样,同样可以有多个测试命令)

       until   test   commands

             other   commands

       done 

 循环处理文件:

                通常需要遍历文件中的数据,这要求结合已经讲过的两种技术:

                                    1、使用嵌套循环

                                    2、修改 IFS 环境变量

下面的例子是从 / etc/passwd 中获取数据,先逐行遍历 / etc/passwd 文件,并将 IFS 变量的值改成冒号,从而分割每行数据中的字段

上述脚本使用两个不同的 IFS 值来解析数据,第一个 IFS 值解析出 / etc/passwd 文件中的单独行,内部 for 循环接着将 IFS 修改为冒号,允许你从 / etc/passwd 的行中解析出单独的值。

控制循环:

      break、continue

1、跳出单个循环

2、跳出内部循环 

               当使用了多重循环时,break 只会退出你所在的最内层循环。

3、跳出外部循环;

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

continue 与 break 用法一样

如果 continue 跳过的循环中包含变量的自增问题就会出现

处理循环的输出:

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

实例:搜索某个文件夹下的可执行文件

            

               

用通配符读取目录:

              可以用 for 命令来自动遍历目录中的文件。进行此操作时必须在文件名或路径名中使用通配符。它会强制 shell 使用文件扩展匹配。

**  #!/bin/bash**

**              #iterate through all the files in a directory**

**              for file in /home/ZHJIAB/test/***

**              do**

**                     if   [-d  "$file"]**

**                     then   **

**                                  echo "$file is a directory"**

**                     elif  [-f  "$file"]**

**                     then**

**                                   echo "$file is a file"**

**                     fi**

**              done**

如果目录名中含有空格,这时候 $file 就要带上引号否则就会报错 too many  argument

C 语言风格的 for 命令:

              bash 中 c 语言风格的 for 命令:

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

              C 语言风格的 for 命令允许为迭代使用多个变量循环会单独处理每个变量,尽管可以使用多个变量但你只能在 for 循环中定义一种条件。

#!/bin/bash

              # multiple variable

              for ((a=1,b=10 ; a<=10 ; a++ , b--))

              do

                     echo "$a - $b"

              done            

while 命令:

       while 命令的基本格式是:

              while  test  command

              do

                     other  commands     

              done

while 命令允许在 while 语句行定义多个测试命令,只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环

#!/bin/bash

              #testing a multicommand while loop

              var1=10

              while  echo $var1

                     [$var1 -ge 0]          #-ge 即为大于等于

              do 

                     echo "This is inside the loop"

                     var1=$[$var1 - 1]                                  #shell 的算数运算操作格式为 $[   ]

              done

until 命令:

              until 命令和 while 命令工作的方式完全相反。until 命令要求你指定一个通常返回非零退出状态码的测试命令只有测试命令的退出状态码不为 0,bash shell 才会执行循环中列出的命令一单测试命令返回了退出状态码 0,循环就结束了。

               (while 循环返回退出状态码 0 则会继续执行循环)

until  test commands

do

       other  commands

done

#!/bin/bash

#using the util command

var1=100

until echo $var1

              [$var1 -eq 0]

do

       echo  Inside  the loop: $var1

       var1=$[$var1 - 25]

done

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

嵌套循环:(nestd loop)

for 嵌套 for:

#!/bin/bash

#using nestd loop

for(( a=1 ; a<=3 ; a++) )

do

       echo "Starting loop $a:"

       for(( b=1 ; b<=3 ; b++) )

       do

              echo "Inside loop : $b"

       done

done

注意:两个循环的 do 和 done 没有任何区别,bash shell 自身能够区别内部循环和外部循环。

while 嵌套 for:     

#!/bin/bash

#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

同样 shell 能够区分 for 循环和 while 循环各自的 do 和 done。

可以自行尝试 while 循环和 until 循环

循环处理文件数据:

              通常必须遍历存储在文件中的数据,这要求结合两种技术:

                            1。使用嵌套循环

                            2。修改 IFS 环境变量 

              通过修改 IFS 环境变量,就能强制 for 命令将文件中的每行都当成单独的一个条目来处理,即便数据中有空格也是如此。一旦从文件中提取出了单独的行,可能需要再次利用循环来提取行中的数据。

              典型的例子是处理 / etc/passwd 文件中的数据

             

  IFS=$'\n'       // 使用换行符做为字段分隔符。

  IFS='\n':;"     // 这个赋值会将反斜杠、n、冒号、分号和双引号作为字段分隔符。

  IFS=$'\n':;"   // 这个赋值会将换行符、冒号、分号和双引号作为字段分隔符。

执行脚本得到如图所示结果

控制循环:

→break 是退出循环的一个简单办法,可以用 break 命令来退出任意类型的循环

              1. 跳出单个循环

              2. 跳出内部循环

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

                     如下例:

      

     

              3. 跳出外部循环

                     有时你在内部循环,但需要停止外部循环。break 命令接受单个命令行参数值:

                                   break  n  

                     其中 n 指定了要跳出的循环层级,默认情况下 n 为 1,表明跳出的是当前的循环。如果将 n 设为 2,break 命令就会停止下一级的外部循环。

       

             

              注意:当 shell 执行了 break 命令后,外部循环就停止了。

continue 命令:

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

             

             

当 if-then 语句的条件被满足时(值大于 5 小于 10),shell 会执行 continue 命令,跳过当前循环中剩余的命令(本例中即为 echo 语句被跳过),但整个循环还会继续,所以显示了 10-15 的数字。           

shell 执行 continue 命令时,它会跳过剩余的命令,如果你在某个条件里对测试条件变量进行增值,问题就出现了。

      

执行脚本你会发现出现了问题(本处将输出结果重定向到 more),当 shell 执行 continue 命令时,它跳过了 while 循环中余下的命令,不幸的是,跳过的部分正是 $var1 计数变量增值的地方,而这个变量又被用于 while 测试命令中,这意味着这个变量值将不会再发生变化。

      

       continue 也允许通过命令行参数指定要继续执行哪一级循环:

                            continue  n

处理循环的输出:

         ..........

              done  > output.txt    

         ..........

              done  | sort

查找可执行文件: