Shell编程—结构化命令(2)

1for命令

for命令的基本格式:

for var in list 
do
    commands 
done

在list参数中,你需要提供迭代中要用到的一系列值。

1.1读取列表中的值

例子:

$ vim test1
#!/bin/bash
# testing the for variable after the looping
 for test in Alabama Alaska Arizona Arkansas California Colorado 
 do
     echo "The next state is $test" 
 done
 echo "The last state we visited was $test" 
 test=Connecticut 
 echo "Wait, now we're visiting $test"
 
 执行结果:
$ ./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
The last state we visited was Colorado 
Wait, now we're visiting Connecticut

1.2读取列表中的复杂值

看这个例子:

$ vim 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

for循环每个值都是用空格分割的。如果有包含空格的数据值,也会导致这种类似的问题,所以处理方法可以采用上面的第二种(加引号)的方式。

1.3从变量读取列表

看例子:

$ vim 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?

1.4从命令读取值

$ vim 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

1.5更改字段分隔符

IFS叫作内部字段分隔符

IFS环境变量定义了bash shell用作字段分隔符的一系列字符。默认情况下,bash shell会将下列字符当作字段分隔符:

  • 空格
  • 制表符
  • 换行符

如果bash shell在数据中看到了这些字符中的任意一个,它就会假定这表明了列表中一个新数据字段的开始。

但是我们可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符。例如,如果你想修改IFS的值,使其只能识别换行符,那就必须这么做:

IFS=$'\n'

将这个语句加入到脚本中,告诉bash shell在数据值中忽略空格和制表符。对前一个脚本使用这种方法,将获得如下输出。

$ vim test5b
#!/bin/bash
# reading values from a file
file="states" 
IFS=$'\n' 
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

1.6用通配符读取目录

$ vim 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 

for命令会遍历/home/rich/test/*输出的结果。该代码用test命令测试了每个条目(使用方括号方法),以查看它是目录还是文件。for后面可以接多个需要循环遍历的路径。注意这里的判断条件“$file”用引号包围起来了,这是为了避免我们目录名和文件名有空格而导致误认为有多个文件而出错。

 

2 C语言风格的for命令

例一:使用单一变量

$ vim test8
#!/bin/bash
# testing the C-style for loop
 for (( i=1; i <= 10; i++ )) 
 do
      echo "The next number is $i" 
 done 
 
 $ ./test8
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
The next number is 6
The next number is 7
The next number is 8
The next number is 9
The next number is 10

例二:使用多个变量

$ vim test9
#!/bin/bash
# multiple variables
 for (( a=1, b=10; a <= 10; a++, b-- )) 
 do 
     echo "$a - $b" 
 done 
 
 $ ./test9
1   - 10
2   - 9
3   - 8
4   - 7
5   - 6
6   - 5
7   - 4
8   - 3
9   - 2
10  - 1

 

3while命令

while命令的格式是:

while test command 
do
   other commands 
done

while命令的关键在于所指定的test command的退出状态码必须随着循环中运行的命令而改变。如果退出状态码不发生变化, while循环就将一直不停地进行下去。

$ vim test11
#!/bin/bash                                                  
# testing a multicommand while loop
var1=5                                                            
while echo $var1       
           [ $var1 -ge 0 ] 
do
    echo "This is inside the loop"     
    var1=$[ $var1 - 1 ] 
done 

$ ./test11
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

while循环会在var1变量等于0时执行echo语句,然后将var1变量的值减一。接下来再次执行测试命令,用于下一次迭代。echo测试命令被执行并显示了var变量的值(现在小于0了)。直到shell执行test测试命令,whle循环才会停止。

 

4until命令

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

格式:

until test commands 
do
    other commands 
done

下面是使用until命令的一个例子。

$ vim 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

使用多个测试命令与while一样。

 

5嵌套循环

在for循环中嵌套for循环的简单例子:

$ vim 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

$ ./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

在while循环内部放置一个for循环:

$ vim 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 

$ ./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 

混用until和while循环:

$ vim test16 
#!/bin/bash 
# using until and while loops 
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 

$ ./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 

 

6控制循环

6.1break命令

1. 跳出单个循环

用for循环举例,当然break命令同样适用于while和until循环:

$ vim test17
#!/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"

$ ./test17
Iteration number: 1
Iteration number: 2
Iteration number: 3
Iteration number: 4
The for loop is completed

2. 跳出外部循环

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

break n

6.2continue命令

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

一个在for循环中使用continue命令的简单例子:

$ vim test21
#!/bin/bash
# using the continue command
 for (( var1 = 1; var1 < 9; var1++ )) 
 do 
    if [ $var1 -gt 3 ] && [ $var1 -lt 6 ]    
    then   
        continue    
    fi    
    echo "Iteration number: $var1" 
done 

$ ./test21
Iteration number: 1
Iteration number: 2
Iteration number: 3
Iteration number: 6
Iteration number: 7
Iteration number: 8

同样地,continue命令也有像break一样的另外两中用法,我们来看一下

continue n
posted @ 2019-12-15 19:34  橘子洲头。  阅读(177)  评论(0编辑  收藏  举报