shell脚本编程之更多结构化命令(一)

简介: shell脚本编程之更多结构化命令(一)

35.jpg

1.for命令


bash shell提供了for命令,允许你创建一个遍历一系列值的循环。每次迭代都使用其中的一个值来执行已定义好的一组命令,for命令的基本格式如下所示:


1for var in list
2do 
3    命令...
4done


在list参数中,需要提供迭代需要的一系列值。可以通过几种不同的方法指定

列表中的值。do和done语句中之间输入的命令可以是一条或者多条标准的bash shell命令。也可以将do语句和for语句放在同一行,但是必须用分号将其同列表中的值分开:for var in list; do


1.1 读取列表中的值


for命令最基本的用法就是遍历for命令自身定义的一系列值,如下例所示:


1#!/bin/bash
 2
 3for li in A B C D E F G
 4do
 5    echo The next state is $li
 6done
 7
 8# 结果
 9[njust@njust tutorials]$ ./dana.sh
10The next state is A
11The next state is B
12The next state is C
13The next state is D
14The next state is E
15The next state is F
16The next state is G


1.2 读取列表中的复杂值


当shell看到list列表中的单引号并尝试使用它们来定义一个单独的数据值时,结果会一团糟。如下例所示:


1#!/bin/bash
 2
 3for var in I don't know if this'll work
 4do 
 5    echo "word:$var"
 6done
 7
 8# 结果
 9word:I
10word:dont know if thisll
1


两种解决方法:


a.使用转义字符来将单引号进行转义;

b.使用双引号来定义用到单引号的值;



1#!/bin/bash
 2
 3for var in I don\'t know if "this'll" work
 4do 
 5    echo "word:$var"
 6done
 7
 8# 结果
 9[njust@njust tutorials]$ ./dana1.sh 
10word:I
11word:don't
12word:know
13word:if
14word:this'll
15word:work


注意:for循环假定每个值都是用空格分割的,如果有包含空格的数据值,就会陷入麻烦。如下例所示:


1#!/bin/bash
 2
 3for var in New York New Mexico North Carolina
 4do
 5    echo "Now going to $var"
 6done
 7
 8# 结果
 9[njust@njust tutorials]$ ./dana2.sh 
10Now going to New
11Now going to York
12Now going to New
13Now going to Mexico
14Now going to North
15Now going to Carolina


for命令用空格来划分列表中的每个值,如果在单独的数据值中有空格,就必须使用双引号将这些值圈起来,在某个值两边使用双引号时,shell并不会将双引号当成值的一部分。如下例所示:



1#!/bin/bash
 2
 3for var in "New York" "New Mexico" "North Carolina"
 4do
 5    echo "Now going to $var"
 6done
 7
 8# 结果
 9[njust@njust tutorials]$ ./dana2.sh 
10Now going to New York
11Now going to New Mexico
12Now going to North Carolina



1.3 从变量读取列表list


通常情况下,是将一系列值都集中存储在一个变量,然后需要遍历变量中的整个列表,如下例所示:


1#!/bin/bash
 2
 3list="Red Green Blue"
 4
 5list=$list" Blank"  # 使用赋值语句向$list变量包含的已有列表中添加一个值Blank,这是向变量中存储的已有文本字符串尾部添加文本的常用方法
 6for var in $list
 7do
 8    echo "The current color is $var"
 9done
10
11# 结果
12[njust@njust tutorials]$ ./dana3.sh 
13The current color is Red
14The current color is Green
15The current color is Blue
16The current color is Blank


1.4 从命令中读取值


生成列表中所需值的另一途径就是使用命令的输出。可以使用命令替换来执行任何能产生输出的命令,然后在for命令中使用该命令的输出。如下例所示:


1#!/bin/bash
 2
 3file="color"
 4for c in $(cat $file)
 5do
 6    echo "beautiful color:$c"
 7done
 8
 9# 结果
10[njust@njust tutorials]$ ./dana4.sh 
11beautiful color:Red
12beautiful color:Green
13beautiful color:Bule
14beautiful color:Pink


上述情况中每种颜色都在单独的一行,而不是通过空格分隔的。但是,这并没有解决数据中用空格的情况


1.5 更改字段分隔符


造成for命令中以空格为分隔符的原因是特殊的环境变量IFS(内部字段分隔符),IFS环境变量定义了bash shell用作字符分隔符的一些列字符。默认情况下,bash shell会将下面的字符当成字段分隔符:


a.空格

b.制表符

c.换行符


如果bash shell在数据中看到了这些字符中的任意一个,它就会假定这表明了列表中一个新数据字段的开始。这会导致在处理含有空格的数据时,显得十分麻烦。解决方法:可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符,如下例所示:


1#!/bin/bash
 2
 3file="color"
 4
 5IFS=$'\n'   # 告诉bash shell在数据值中忽略空格和制表符,仅识别换行符!
 6
 7for c in $(cat $file)
 8do
 9    echo "beautiful color:$c"
10done
11
12# 结果
13[njust@njust tutorials]$ ./dana4.sh 
14beautiful color:Red
15beautiful color:Green
16beautiful color:Bule
17beautiful color:Pink
18beautiful color:Deep Purple


在处理代码量较大的脚本时,可能在一个地方需要修改IFS值。在脚本的其他地方继续沿用默认的IFS值。一个可行的方法是在改变IFS之前保存原来的IFS值,之后再恢复它,这样保证了在脚本的后续操作中继续使用的是默认的IFS值。


1IFS.OLD=$IFS
2
3IFS=$'\n'
4<在代码中使用新的IFS值>
5IFS=$IFS.OLD


IFS环境变量的其他一些绝妙用法,假如你要遍历一个文件中用冒号分隔的值(比如/etc/passwd文件),你需要做的就是将IFS设置为冒号IFS=:。


如果要指定多个IFS字符,只要将它们在赋值行串起来就行,如IFS=$'\n':;"。


1.6 用通配符读取目录


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


1#!/bin/bash
 2
 3for file in /home/njust/tutorials/*
 4do
 5
 6    if [ -d "$file" ]  # 在linux中文件名或目录名中包含空格是合法的,要解决这个问题可以将$file变量用双引号圈起来。如果不这样的话遇到含空格的目录名或文件名时会报错!
 7    then
 8        echo "$file is a directory"
 9    elif [ -f "$file" ]
10    then
11        echo "$file is a file"
12    fi
13done
14
15# 结果
16[njust@njust tutorials]$ ./dana5.sh 
17/home/njust/tutorials/case.sh is a file
18/home/njust/tutorials/color is a file
19/home/njust/tutorials/curry.sh is a file
20/home/njust/tutorials/dana is a file
21/home/njust/tutorials/dana1.sh is a file
22/home/njust/tutorials/dana2.sh is a file
23/home/njust/tutorials/dana3.sh is a file
24/home/njust/tutorials/dana4.sh is a file
25/home/njust/tutorials/dana5.sh is a file
26/home/njust/tutorials/dana.sh is a file


也可以在for命令中列出多个目录通配符,将目录查找和列表合并进同一个for语句,如下例所示:


1#!/bin/bash
 2
 3for file in /home/njust/.b* /home/njust/tutorials
 4do
 5
 6    if [ -d "$file" ]
 7    then
 8        echo "$file is a directory"
 9    elif [ -f "$file" ]
10    then
11        echo "$file is a file"
12    else
13        echo "$file doesn't exist"
14    fi
15done
16
17# 结果
18[njust@njust tutorials]$ ./dana6.sh 
19/home/njust/.bash_history is a file
20/home/njust/.bash_logout is a file
21/home/njust/.bash_profile is a file
22/home/njust/.bashrc is a file
23/home/njust/tutorials is a directory


2.C语言风格的for命令



bash shell也支持一种for循环,它看起来与C语言风格的for循环类似,但有一些细微的不同。bash中C语言风格的for循环基本格式如下


1for (( 变量初始化; 条件; 变量迭代变化 ))


注意:有些部分并没有遵循bash shell标准的for命令。如下所示:


a.变量赋值可以有空格;b.条件中的变量不以美元符开头;c.迭代过程的算式未使用expr命令格式;下面是在bash shell程序中使用C语言风格的for命令:



1#!/bin/bash
 2
 3for (( i = 1; i <= 10; i++ )) 
 4do 
 5    echo "The next number is $i"
 6done
 7
 8# 结果
 9[njust@njust tutorials]$ ./dana7.sh 
10The next number is 1
11The next number is 2
12The next number is 3
13The next number is 4
14The next number is 5
15The next number is 6
16The next number is 7
17The next number is 8
18The next number is 9
19The next number is 10


2.1 使用多个变量


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


1#!/bin/bash
 2
 3# mutiple variables
 4
 5for (( a = 1, b = 10; a <= 10; a++, b-- ))
 6do 
 7    echo "$a - $b"
 8done
 9
10# 结果
11[njust@njust tutorials]$ ./dana8.sh 
121 - 10
132 - 9
143 - 8
154 - 7
165 - 6
176 - 5
187 - 4
198 - 3
209 - 2
2110 - 1


3.while命令

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


3.1 while的基本格式


1while test 命令
2do
3    命令
4done


while命令的关键点:所指定的test 命令的退出状态码必须随着循环中运行的命令而改变。如果退出状态码不发生改变,while循环就会一直不停地执行下去。最常见的test 命令的用法是用方括号检查循环命令中用到的shell变量的值,如下所示:


1#!/bin/bash
 2
 3var1=10
 4while [ $var1 -gt 0 ]
 5do 
 6    echo $var1
 7    var1=$[ $var1 - 1 ]
 8done
 9
10# 结果
11[njust@njust tutorials]$ ./dana9.sh 
1210
139
148
157
166
175
184
193
202
211

3.2 使用多个测试命令

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



1#!/bin/bash
 2
 3var=10
 4
 5while echo $var
 6    [ $var  -ge 0 ]
 7do
 8    echo "This is inside in the loop"
 9    var=$[ $var - 1 ]
10done
11
12# 结果
13[njust@njust tutorials]$ ./dana10.sh 
1410
15This is inside in the loop
169
17This is inside in the loop
188
19This is inside in the loop
207
21This is inside in the loop
226
23This is inside in the loop
245
25This is inside in the loop
264
27This is inside in the loop
283
29This is inside in the loop
302
31This is inside in the loop
321
33This is inside in the loop
340
35This is inside in the loop
36-1


在含有多个命令的while语句中,在每次迭代中所有测试命令都会被执行,包括测试命令失败的最后一次迭代。注意:指定多个测试命令时,每个测试命令都出现在单独的一行


4.until命令


until命令与while命令工作方式相反,until命令要求你指定一个通常返回非零状态码的测试命令。只有测试命令的退出状态码非零,bash shell才会执行循环中列出的命令。一旦测试命令返回退出状态码0,循环就结束了。until命令的基本格式如下所示:


1until test 命令
2do
3    命令
4done


可以在until命令语句中放入多个测试命令,只有最后一个命令的退出状态码决定了bash shell是否执行已定义的命令。如下例所示:


1#!/bin/bash
 2
 3var=100
 4
 5until [ $var -eq 0 ]
 6do
 7    echo $var
 8    var=$[ $var - 25 ]
 9done
10
11# 结果
12[njust@njust tutorials]$ ./dana11.sh 
13100
1475
1550
1625

与while命令相似,until命令在使用多个测试命令时要注意。shell会执行指定的多个测试命令,只有在最后一个命令成立时才会停止。如下例所示:

1#!/bin/bash
 2
 3var=100
 4
 5until echo $var
 6    [ $var -eq 0 ]
 7do
 8    echo "Inside the loop: $var"
 9    var=$[ $var - 25 ]
10done
11
12# 结果
13[njust@njust tutorials]$ ./dana12.sh 
14100
15Inside the loop: 100
1675
17Inside the loop: 75
1850
19Inside the loop: 50
2025
21Inside the loop: 25
220


5.嵌套循环



循环语句可以在循环内使用任意类型的命令,包括其他循环命令。这种循环称为嵌套循环。注意:使用嵌套循环时,在迭代中使用迭代,与命令运行的次数是乘积关系。如下例所示:


1#!/bin/bash
 2
 3for (( a = 1; a <= 3; a++ ))
 4do
 5    echo "Starting loop $a:"
 6    for (( b = 1; b <= 3; b++ ))
 7    do
 8        echo "  Inside loop:$b"
 9    done
10done
11
12# 结果
13[njust@njust tutorials]$ ./dana13.sh 
14Starting loop 1:
15Inside loop:1
16Inside loop:2
17Inside loop:3
18Starting loop 2:
19Inside loop:1
20Inside loop:2
21Inside loop:3
22Starting loop 3:
23Inside loop:1
24Inside loop:2
25Inside loop:3


在混用循环命令时也一样,比如在while循环内部放置一个for循环。如下例所示:


1#!/bin/bash
 2
 3var1=5
 4
 5while [ $var1 -ge 0 ]
 6do
 7    echo "Outer loop: $var1"
 8    for (( var2 = 1; $var2 < 3; var2++ ))
 9    do
10        var3=$[ $var1 * $var2 ]
11        echo "  Inner loop: $var1 * $var2 = $var3"
12    done
13    var1=$[ $var1 - 1 ]
14done
15
16# 结果
17[njust@njust tutorials]$ ./dana14.sh 
18Outer loop: 5
19Inner loop: 5 * 1 = 5
20Inner loop: 5 * 2 = 10
21Outer loop: 4
22Inner loop: 4 * 1 = 4
23Inner loop: 4 * 2 = 8
24Outer loop: 3
25Inner loop: 3 * 1 = 3
26Inner loop: 3 * 2 = 6
27Outer loop: 2
28Inner loop: 2 * 1 = 2
29Inner loop: 2 * 2 = 4
30Outer loop: 1
31Inner loop: 1 * 1 = 1
32Inner loop: 1 * 2 = 2
33Outer loop: 0
34Inner loop: 0 * 1 = 0
35Inner loop: 0 * 2 = 0


相关文章
|
18天前
|
Web App开发 Java Linux
Linux之Shell基本命令篇
Linux之Shell基本命令篇
Linux之Shell基本命令篇
|
5天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
33 3
|
2天前
|
监控 Shell 应用服务中间件
第十二章 Shell脚本编写及常见面试题(二)
第十二章 Shell脚本编写及常见面试题(二)
|
2天前
|
监控 关系型数据库 Shell
第十二章 Shell脚本编写及常见面试题(一)
第十二章 Shell脚本编写及常见面试题(一)
|
2天前
|
监控 Shell
生产环境Shell脚本Ping监控主机是否存活(多种方法)
生产环境Shell脚本Ping监控主机是否存活(多种方法)
|
2天前
|
运维 Shell
Shell脚本判断IP是否合法性(多种方法)
Shell脚本判断IP是否合法性(多种方法)
|
6天前
|
存储 Shell 数据安全/隐私保护
ZooKeeper【基础知识 04】控制权限ACL(原生的 Shell 命令)
【4月更文挑战第11天】ZooKeeper【基础知识 04】控制权限ACL(原生的 Shell 命令)
25 7
|
8天前
|
运维 监控 Shell
利用Shell脚本编写局域网监控软件:实时监测主机连接情况
本文介绍了如何使用Shell脚本创建一个局域网监控工具,以实时检查主机连接状态。脚本包括扫描IP地址范围检测主机可达性及使用`netstat`监控ESTABLISHED连接。此外,还展示了如何每60秒将连接数数据自动提交到指定网站API,以便实时跟踪网络活动。这个自动化监控系统有助于提升网络安全性和故障排查效率。
32 0
|
9天前
|
监控 Shell 开发工具
Shell编程
Shell编程
|
9天前
|
Shell
Shell脚本之流程控制语句
Shell脚本之流程控制语句