Linux bash shell的循环命令for、while和until
1、for命令
for命令,允许你创建一个遍历一系列值的循环,每次迭代都使用其中一个 值来执行已定义好的一组命令。
for var in list
do
commands
done
# 在list参数中,你需要提供迭代中要用到的一系列值。
# 可以通过几种不同的方法指定列表中的值。
在每次迭代中,变量var会包含列表中的当前值,第一次迭代会使用列表中的第一个值,第
二次迭代使用第二个值,以此类推,直到列表中的所有值都过一遍
在do和done语句之间输入的命令可以是一条或多条标准的bash shell命令。
# 也可以写成:
for var in list ; do
1)读取列表中的值
#!/bin/bash
# basic for command
for test in Alabama Alaska Arizona Arkansas California Colorado
do
echo The next state is $test
done
# 执行上述脚本文件test1
$ ./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
#!/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"
# 执行上述脚本文件test1b
$ ./test1b
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
2) 读取列表中复杂值
列表值中的单引号会使得shell读取出错,有两种解决方法:
- 使用转义字符(反斜线)来将单引号转义;
- 使用双引号来定义用到单引号的值。
#!/bin/bash
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循环假定每个值都是用空格分割的,如果有包含空格的数据值,就无法获取。
如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。
#!/bin/bash
for test in Nevada "New Hampshire" "New Mexico" "New York"
do
echo "Now going to $test"
done
# 执行上述脚本文件test3
$ ./test3
Now going to Nevada
Now going to New Hampshire
Now going to New Mexico
Now going to New York
在某个值两边使用双引号时,shell并不会将双引号当成值的一部分。
3)从变量读取列表
将一系列值都集中存储在了一个变量中,然后需要遍历变量 中的整个列表,也可以通过for命令完成。
#!/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
$ ./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?
代码还是用了另一个赋值语句向$list 变量包含的已有列表中添加(或者说是拼接)了一个值,这是向变量中存储的已有文本字符串尾部添加文本的一个常用方法。
4)从命令读取值
可以用命令替换来执行任何能产生输出的命令,然后在for命令中使用该命令的输出。
#!/bin/bash
# reading values from a file
file="states"
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
# 上述是脚本文件test5
$ cat states
Alabama
Alaska
Arizona
Arkansas
Colorado
Connecticut
Delaware
Florida
Georgia
# 变量states
# 执行命令
$ ./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
在命令替换中使用了cat命令来输出文件states的内容,到states文件中每一行有一个州,而不是通过空格分隔的。假定每个州都是在单独的一行上,列出了一个名字中有空格的州,for命令仍然会将每个单词当作单独的值。
上述范例将文件名赋给变量,文件名中没有加入路径。这要求文件和脚本位于同一个目录中,如果不是的话,需要使用全路径名(不管是绝对路径还是相对路径)来引用文件位置。
5)更改字段分隔符
内部字段分隔符(internal field separator),IFS环境变量定义了bash shell用作字段分隔符的一系列字符。默认情况下,bash shell会将下列字符当作字段分隔符:
- 空格
- 制表符
- 换行符
bash shell看到这些字符会认为是列表中新数据字段开始,在处理含有空格的数据(比如文件名)时,到空格符就终止而不是继续识别本应组合在一起的字符串。
修改IFS的值使其只能识别换行符:IFS=$'\n',识别到换行符才是新数据字段开始。
#!/bin/bash
# reading values from a file
file="states"
IFS=$'\n' # 修改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.OLD=$IFS
IFS=$'\n'
#<在代码中使用原来的IFS值>
IFS=$IFS.OLD
6) 用通配符读取目录
用for命令来自动遍历目录中的文件。
#!/bin/bash
for file in /home/rich/test/*
do
if [ -d "$file" ] # $file 用双引号圈起来,因为在Linux中目录或文件名中包含空格是合法的
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done# 运行上述脚本文件test6
./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
2、C语言风格的for命令
遵循bash shell标准的for命令:
- 变量赋值可以有空格
- 条件中的变量不以美元符开头
- 迭代过程的算式未用expr命令格式
#!/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
C语言风格的for命令也允许为迭代使用多个变量,但只能在for循环中定义一种条件。
#!/bin/bash
# multiple variables
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
# 执行上述脚本文件 test9
./test9
1 - 10
2 - 9
3 - 8
4 - 7
5 - 6
6 - 5
7 - 4
8 - 3
9 - 2
10 - 1
3、while命令
# while命令的格式是:
while test command
do
other commands
done
while命令允许定义一个要测试的命令,定义的测试命令返回退出状态码是0,执行下一步命令;test命令返回非零退出状态码时,while命令会停止执行那组命令。
最常见的test command用法:用方括号来检查循环命令中用到的shell变量的值。
#!/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
$