• SHELL学习笔记三


    SHELL学习笔记一

    SHELL学习笔记二

    SHELL学习笔记三

    for 命令

    which

    until 命令
    循环处理文件数据
    控制循环

    处理循环输出

     for 命令

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

     读取列表中的复杂值

    •  使用转义字符(反斜线)来将单引号转义;
    •  使用双引号来定义用到单引号的值。
    $ cat test2 
    #!/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 
    $ ./test2 
    word:I 
    word:don't 
    word:know 
    word:if 
    word:this'll 
    word:work 
    $ 

     从变量读取列表

    $ cat test4 
    #!/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 
    $ ./test4 
    Have you ever visited Alabama? 
    Have you ever visited Alaska? 
    Have you ever visited Arizona? 
    Have you ever visited Arkansas? 
    Have you ever visited Colorado? 
    Have you ever visited Connecticut? 
    $ 

     从命令读取值

    $ cat test5 
    #!/bin/bash 
    # reading values from a file 
     
    file="states" 
     
    for state in $(cat $file) 
    do 
        echo "Visit beautiful $state" 
    done 
    $ cat states 
    Alabama 
    Alaska 
    Arizona 
    Arkansas 
    Colorado 
    Connecticut 
    Delaware 
    Florida 
    Georgia 
    $ ./test5 
    Visit beautiful Alabama 
    Visit beautiful Alaska 
    Visit beautiful Arizona 
    Visit beautiful Arkansas 
    Visit beautiful Colorado 
    Visit beautiful Connecticut 
    Visit beautiful Delaware 
    Visit beautiful Florida 
    Visit beautiful Georgia 
    $ 

     更改字段分隔符

    造成这个问题的原因是特殊的环境变量 IFS ,叫作内部字段分隔符(internal field separator)。IFS 环境变量定义了bash shell用作字段分隔符的一系列字符。默认情况下,bash shell会将下列字符当作字段分隔符:

    •  空格
    •  制表符
    •  换行符
    将这个语句加入到脚本中,告诉bash shell在数据值中忽略空格和制表符。对前一个脚本使用
    这种方法,将获得如下输出。 
    $ cat test5b 
    #!/bin/bash 
    # reading values from a file 
    file="states"  
    IFS=$'
    ' 
    for state in $(cat $file) 
    do 
        echo "Visit beautiful $state" 
    done 
    $ ./test5b 
    Visit beautiful Alabama 
    Visit beautiful Alaska 
    Visit beautiful Arizona 
    Visit beautiful Arkansas 
    Visit beautiful Colorado 
    Visit beautiful Connecticut 
    Visit beautiful Delaware 
    Visit beautiful Florida 
    Visit beautiful Georgia 
    Visit beautiful New York 
    Visit beautiful New Hampshire 
    Visit beautiful North Carolina 
    $ 

    警告  在处理代码量较大的脚本时,可能在一个地方需要修改 IFS 的值,然后忽略这次修改,在脚本的其他地方继续沿用 IFS 的默认值。一个可参考的安全实践是在改变 IFS 之前保存原来的 IFS 值,之后再恢复它。 这种技术可以这样实现:
      IFS.OLD=$IFS
      IFS=$' '
      <在代码中使用新的IFS值>
      IFS=$IFS.OLD
      这就保证了在脚本的后续操作中使用的是 IFS 的默认值。

      用通配符读取目录

    $ cat test6 
    #!/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 
    $ ./test6 
    /home/rich/test/dir1 is a directory 
    /home/rich/test/myprog.c is a file 
    /home/rich/test/myprog is a file 
    /home/rich/test/myscript is a file 
    /home/rich/test/newdir is a directory 
    /home/rich/test/newfile is a file 
    /home/rich/test/newfile2 is a file 
    /home/rich/test/testdir is a directory 
    /home/rich/test/testing is a file 
    /home/rich/test/testprog is a file 
    /home/rich/test/testprog.c is a file 
    $ 

    which

    while test   command 
    do 
      other   commands 
    done 
    $ cat test10 
    #!/bin/bash 
    # while command test 
     
    var1=10 
    while [ $var1 -gt 0 ] 
    do 
        echo $var1 
        var1=$[ $var1 - 1 ] 
    done 
    $ ./test10 
    10 
    9 
    8 
    7 
    6 
    5 
    4 
    3 
    2 
    1 
    $ 

    使用多个测试命令
    while 命令允许你在 while 语句行定义多个测试命令。只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环。如果你不够小心,可能会导致一些有意思的结果。下面的例子将说明这一点。

    $ cat test11 
    #!/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 
    $ ./test11 
    10 
    This is inside the loop 
    9 
    This is inside the loop 
    8 
    This is inside the loop 
    7 
    This is inside the loop 
    6 
    This is inside the loop 
    5 
    This is inside the loop 
    4 
    This is inside the loop 
    3 
    This is inside the loop 
    2 
    This is inside the loop 
    1 
    This is inside the loop 
    0 
    This is inside the loop 
    -1 
    $ 

    until 命令

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

    until test commands 
    do 
        other commands 
    done 
    $ cat test12 
    #!/bin/bash 
    # using the until command 
     
    var1=100 
     
    until [ $var1 -eq 0 ] 
    do 
        echo $var1 
        var1=$[ $var1 - 25 ] 
    done 
    $ ./test12 
    100 
    75 
    50 
    25 
    $

    循环处理文件数据

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

    •  使用嵌套循环
    •  修改 IFS 环境变量

    通过修改 IFS 环境变量,就能强制 for 命令将文件中的每行都当成单独的一个条目来处理,即便数据中有空格也是如此。一旦从文件中提取出了单独的行,可能需要再次利用循环来提取行中的数据。
    典型的例子是处理/etc/passwd文件中的数据。这要求你逐行遍历/etc/passwd文件,并将 IFS变量的值改成冒号,这样就能分隔开每行中的各个数据段了。

    #!/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 
    $ 
    
    Values in rich:x:501:501:Rich Blum:/home/rich:/bin/bash - 
       rich 
       x 
      501 
        501 
        Rich Blum 
        /home/rich 
        /bin/bash 
     Values in katie:x:502:502:Katie Blum:/home/katie:/bin/bash - 
        katie 
        x 
        506 
        509 
        Katie Blum 
        /home/katie 
        /bin/bash 

     控制循环

    • break 命令
    • continue 命令

    break

    break 命令接受单个命令行参数值: 
    break n 
    其中 n 指定了要跳出的循环层级。默认情况下, n 为 1 ,表明跳出的是当前的循环。如果你将n 设为 2 , break 命令就会停止下一级的外部循环。 
    $ cat test20 
    #!/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 
    $ ./test20 
    Outer loop: 1 
       Inner loop: 1 
       Inner loop: 2 
       Inner loop: 3 

     continue 命令

    continue 命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。可以在循环内部设置shell不执行命令的条件。这里有个在 for 循环中使用 continue 命令的简单例子。

    $ cat test21 
    #!/bin/bash 
    # using the continue command 
     
    for (( var1 = 1; var1 < 15; var1++ )) 
    do 
       if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] 
       then 
          continue 
       fi 
       echo "Iteration number: $var1" 
    done 
    $ ./test21 
    Iteration number: 1 
    Iteration number: 2 
    Iteration number: 3 
    Iteration number: 4 
    Iteration number: 5 
    Iteration number: 10 
    Iteration number: 11 
    Iteration number: 12 
    Iteration number: 13 
    Iteration number: 14 
    $ 

    处理循环输出

    #shell会将 for 命令的结果重定向到文件output.txt中,而不是显示在屏幕上。
    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 
  • 相关阅读:
    Redis分布式缓存系列(六)- Redis中的List类型
    Redis分布式缓存系列(五)- Redis中的ZSet类型
    Redis分布式缓存系列(四)- Redis中的Set类型
    Redis分布式缓存系列(三)- Redis中的Hash类型
    Redis分布式缓存系列(二)- Redis中的String类型以及使用Redis解决订单秒杀超卖问题
    Redis分布式缓存系列(一)- Redis客户端及服务端的安装
    .NET中常用的数据结构
    面向对象23种设计模式系列(四)- 迭代器模式
    .NET中的本地缓存(数据分拆+lock锁)
    .NET中的GC垃圾回收
  • 原文地址:https://www.cnblogs.com/aongao/p/11732482.html
Copyright © 2020-2023  润新知