首页 > 代码库 > Linux Shell脚本编写——使用结构化命令(三)

Linux Shell脚本编写——使用结构化命令(三)

for命令

for var in list
do
  commands
done

代码2-1

root@lejian:/data# cat demo1 
#!/bin/bash
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"
root@lejian:/data# ./demo1 
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 Colorado
The last state we visited was California Colorado
Wait, now we‘re visiting Connecticut

如代码2-1所示,如果想要打印的字符串包含空格,可以用""引号包装

 

for循环有时候会遇到特殊符号:

  • 使用转义字符来将单引号转义
  • 使用双引号来定义单引号的值

代码2-2

root@lejian:/data# cat demo2 
#!/bin/bash
echo "print I don‘t know if this‘ll work"
for test in I don‘t know if this‘ll work
do
        echo "word:$test"
done
echo "——————————————————————————————"
for test in I don\‘t know if this\‘ll work
do
        echo "word:$test"
done
echo "——————————————————————————————"
for test in I don"‘"t know if this"‘"ll work
do
        echo "word:$test"
done
root@lejian:/data# ./demo2 
print I don‘t know if this‘ll work
word:I
word:dont know if thisll
word:work
——————————————————————————————
word:I
word:don‘t
word:know
word:if
word:this‘ll
word:work
——————————————————————————————
word:I
word:don‘t
word:know
word:if
word:this‘ll

  

for循环是根据空格来区分的,如果遇到包含空格的字符,可用双引号括起来

代码2-3

root@lejian:/data# cat demo3 
#!/bin/bash
for test in Nevada "New Hampshire" "New Mexico" "New York"
do
        echo "Now going to $test"
done
root@lejian:/data# ./demo3 
Now going to Nevada
Now going to New Hampshire
Now going to New Mexico
Now going to New York

 

从变量读取列表

代码2-4

root@lejian:/data# cat demo4
#!/bin/bash
list="Alabama Alaska Arizona Arkansas California Colorado"
list=$list" Connecticut"
for state in $list
do
echo "Have you ever visited $state?"
done
root@lejian:/data# ./demo4
Have you ever visited Alabama?
Have you ever visited Alaska?
Have you ever visited Arizona?
Have you ever visited Arkansas?
Have you ever visited California?
Have you ever visited Colorado?
Have you ever visited Connecticut?

 

从命令中读取值  

 代码2-5

root@lejian:/data# cat state 
Alabama 
Alaska 
Arizona 
Arkansas 
California 
Colorado 
Connecticut
root@lejian:/data# cat demo5 
#!/bin/bash
file=state
for state in `cat $file`
do
        echo "visit beautiful $state"
done
root@lejian:/data# ./demo5 
visit beautiful Alabama
visit beautiful Alaska
visit beautiful Arizona
visit beautiful Arkansas
visit beautiful California
visit beautiful Colorado
visit beautiful Connecticut

  

 修改字段分隔符,使用IFS=$‘;‘

代码2-6

root@lejian:/data# cat states 
Alabama;Alaska;Arizona;Arkansas;California;Colorado;Connecticut
root@lejian:/data# cat demo6 
#!/bin/bash
file="states"
IFS=$‘;‘
for state in `cat $file`
do
        echo "visit beautiful $state"
done
root@lejian:/data# ./demo6 
visit beautiful Alabama
visit beautiful Alaska
visit beautiful Arizona
visit beautiful Arkansas
visit beautiful California
visit beautiful Colorado
visit beautiful Connecticut

  

 默认情况下,bash shell会把下列字符当做字段分隔符:

  • 空格
  • 制表符
  • 换行符

 

用通配符读取目录

用for循环命令来自动遍历满是文件的目录,进行此操作时,必须在文件名或路径名中使用通配符。它会强制shell使用文件扩展匹配。文件扩展匹配是生成匹配指定的通配符的文件名或路径名的过程

代码2-7

root@lejian:/data# ls -l /home/software/apache-tomcat-1/
total 120
drwxr-xr-x 2 root root  4096 Nov 25  2014 bin
drwxr-xr-x 3 root root  4096 Nov 26  2014 conf
drwxr-xr-x 2 root root  4096 Nov 25  2014 lib
-rw-r--r-- 1 root root 56977 Nov  3  2014 LICENSE
drwxr-xr-x 2 root root 12288 Dec  3 01:21 logs
-rw-r--r-- 1 root root  1397 Nov  3  2014 NOTICE
-rw-r--r-- 1 root root  6779 Nov  3  2014 RELEASE-NOTES
-rw-r--r-- 1 root root 16204 Nov  3  2014 RUNNING.txt
drwxr-xr-x 2 root root  4096 Nov 25  2014 temp
drwxr-xr-x 2 root root  4096 Nov 25  2014 webapps
drwxr-xr-x 3 root root  4096 Nov 25  2014 work
root@lejian:/data# ls -l /home/software/apache-tomcat-1/conf/
total 212
drwxr-xr-x 3 root root   4096 Nov 25  2014 Catalina
-rw------- 1 root root  12374 Nov  3  2014 catalina.policy
-rw------- 1 root root   6427 Nov  3  2014 catalina.properties
-rw------- 1 root root   1577 Nov  3  2014 context.xml
-rw------- 1 root root   3387 Nov  3  2014 logging.properties
-rw------- 1 root root   6491 Nov 25  2014 server.xml
-rw------- 1 root root   1744 Nov  3  2014 tomcat-users.xml
-rw------- 1 root root   1846 Nov  3  2014 tomcat-users.xsd
-rw------- 1 root root 163468 Nov  3  2014 web.xml
root@lejian:/data# cat demo1 
#!/bin/bash
for file in /home/software/apache-tomcat-1/* /home/software/apache-tomcat-1/conf/*
do
        if [ -d $file ]
        then
                echo "$file is a directory"
        elif [ -f $file ]
        then
                echo "$file is a file"
        else
                echo "$file doesn‘t exists"
        fi
done
root@lejian:/data# ./demo1 
/home/software/apache-tomcat-1/bin is a directory
/home/software/apache-tomcat-1/conf is a directory
/home/software/apache-tomcat-1/lib is a directory
/home/software/apache-tomcat-1/LICENSE is a file
/home/software/apache-tomcat-1/logs is a directory
/home/software/apache-tomcat-1/NOTICE is a file
/home/software/apache-tomcat-1/RELEASE-NOTES is a file
/home/software/apache-tomcat-1/RUNNING.txt is a file
/home/software/apache-tomcat-1/temp is a directory
/home/software/apache-tomcat-1/webapps is a directory
/home/software/apache-tomcat-1/work is a directory
/home/software/apache-tomcat-1/conf/Catalina is a directory
/home/software/apache-tomcat-1/conf/catalina.policy is a file
/home/software/apache-tomcat-1/conf/catalina.properties is a file
/home/software/apache-tomcat-1/conf/context.xml is a file
/home/software/apache-tomcat-1/conf/logging.properties is a file
/home/software/apache-tomcat-1/conf/server.xml is a file
/home/software/apache-tomcat-1/conf/tomcat-users.xml is a file
/home/software/apache-tomcat-1/conf/tomcat-users.xsd is a file
/home/software/apache-tomcat-1/conf/web.xml is a file

注:如果文件名或目录名包含空格,判断是否是文件还是目录需要使用双引号[ -d "$file" ]  

 

C语言for循环风格

代码2-9

root@lejian:/data# cat demo2 
#!/bin/bash
for ((i=1;i<10;i++))
do
        echo "The next number is $i"
done
echo "——————————————————————————"
for ((a=1,b=10;a<10;a++,b--))
do
        echo "$a - $b = `expr $a - $b`"
done
root@lejian:/data# ./demo2 
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
——————————————————————————
1 - 10 = -9
2 - 9 = -7
3 - 8 = -5
4 - 7 = -3
5 - 6 = -1
6 - 5 = 1
7 - 4 = 3
8 - 3 = 5
9 - 2 = 7

  

while命令

while命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码0。它会在每个迭代的一开始测试test命令。在test命令返回非0退出状态码时,while命令会停止执行那组命令

while test command
do
  other commands
done

代码2-10

root@lejian:/data# cat demo3 
#!/bin/bash
val=10
while [ $val -gt 0 ]
do
        echo $val
        ((val--))
done
root@lejian:/data# ./demo3 
10
9
8
7
6
5
4
3
2
1

  

 使用多个测试命令

 while命令行允许定义多个测试命令,只有最后一个测试命令的退出状态码会被用来什么时候退出循环(注:多行命令必须用回车隔开)

 代码2-11 

root@lejian:/data# cat demo4 
#!/bin/bash
val=10
while   echo $val
        [ $val -gt 0 ]
do
        echo "This is inside the loop"
        ((val--))
done
root@lejian:/data# ./demo4 
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

  

until命令

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

until test commands
do
  other commands
done

代码2-12

root@lejian:/data# cat demo5 
#!/bin/bash
val=100
until [ $val -eq 0 ]
do
        echo $val
        val=$[ $val - 25 ]
done
root@lejian:/data# ./demo5 
100
75
50
25

  

嵌套循环

代码2-13

root@lejian:/data# cat demo6 
#!/bin/bash
for ((a=1;a<=3;a++))
do
        echo "Starting loop $a:"
        for ((b=1;b<=3;b++))
        do
                echo "Inside loop:$b"
        done
done
root@lejian:/data# ./demo6 
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

  

循环处理文件数据:

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

循环处理文件数据

代码2-14

root@lejian:/data# cat passwd 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
root@lejian:/data# cat demo1 
#!/bin/bash
IFS=$‘\n‘
for entry in `cat passwd`
do
        echo "Values in $entry"
        IFS=$‘:‘
        for value in $entry
        do
                echo "  $value"
        done
done
root@lejian:/data# ./demo1 
Values in root:x:0:0:root:/root:/bin/bash
        root
        x
        0
        0
        root
        /root
        /bin/bash
Values in daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
        daemon
        x
        1
        1
        daemon
        /usr/sbin
        /usr/sbin/nologin
Values in bin:x:2:2:bin:/bin:/usr/sbin/nologin
        bin
        x
        2
        2
        bin
        /bin
        /usr/sbin/nologin

  

 控制循环:

  • break命令
  • continue命令

代码2-15

root@lejian:/data# cat demo2 
#!/bin/bash
for val in 1 2 3 4 5 6 7 8 9
do
        if [ $val -eq 6 ]
        then
                break
        fi
        echo "Iteration number:$val"
done
echo "The for loop is completed"
root@lejian:/data# ./demo2 
Iteration number:1
Iteration number:2
Iteration number:3
Iteration number:4
Iteration number:5
The for loop is completed

  

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

 代码2-16

root@lejian:/data# cat demo3 
#!/bin/bash
for ((a = 1;a<5;i++))
do
        echo "Outer loop $a:"
        for ((b=1;b<100;b++))
        do
                if [ $b -gt 6 ]
                then 
                        break 2
                fi
                echo "Inner loop:$b"
        done
done
root@lejian:/data# ./demo3 
Outer loop 1:
Inner loop:1
Inner loop:2
Inner loop:3
Inner loop:4
Inner loop:5
Inner loop:6

  

continue命令

代码2-17

root@lejian:/data# cat demo4 
#!/bin/bash
for ((val=1;val<16;val++))
do
        if [ $val -gt 5 ] && [ $val -lt 11 ]
        then
                continue
        fi
        echo "Iteration number:$val"
done
root@lejian:/data# ./demo4 
Iteration number:1
Iteration number:2
Iteration number:3
Iteration number:4
Iteration number:5
Iteration number:11
Iteration number:12
Iteration number:13
Iteration number:14
Iteration number:15

  

 和break命令一样,continue n也允许通过命令参数指定要继续哪一级循环

 代码2-18

root@lejian:/data# cat demo5 
#!/bin/bash
for ((a=1;a<6;a++))
do
        echo "Iteration $a:"
        for ((b=1;b<3;b++))
        do
                if [ $a -gt 2 ] && [ $a -lt 5 ]
                then
                        continue 2
                fi
                val=$[ $a * $b ]
                echo " The result of $a * $b = $val "
        done
done
root@lejian:/data# ./demo5 
Iteration 1:
 The result of 1 * 1 = 1 
 The result of 1 * 2 = 2 
Iteration 2:
 The result of 2 * 1 = 2 
 The result of 2 * 2 = 4 
Iteration 3:
Iteration 4:
Iteration 5:
 The result of 5 * 1 = 5 
 The result of 5 * 2 = 10 

  

 处理循环的输出

 done命令后面可添加重定向输出,可将命令输出到文件中而不是屏幕上

代码2-19

root@lejian:/data# cat passwd 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
root@lejian:/data# cat demo6 
#!/bin/bash
for file in `cat passwd`
do
        echo "The file content:$file"
done > text
root@lejian:/data# ./demo6 
root@lejian:/data# cat text 
The file content:root:x:0:0:root:/root:/bin/bash
The file content:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
The file content:bin:x:2:2:bin:/bin:/usr/sbin/nologin

  

done命令适用于将循环的结果管接到另一个命令,再重定向到文件或者屏幕,还可以使用其他命令显示到屏幕上

root@lejian:/data# cat demo7 
#!/bin/bash
for state in "North Dakota" Connecticut Illnois Alabama Tennessee
do
        echo "$state is the next place to go"
done | sort > text
echo "This completes our travels"

root@lejian:/data# ./demo7 
This completes our travels
root@lejian:/data# cat text 
Alabama is the next place to go
Connecticut is the next place to go
Illnois is the next place to go
North Dakota is the next place to go
Tennessee is the next place to go

  

 

Linux Shell脚本编写——使用结构化命令(三)