循环不管在程序中还是脚本中都需要经常用到,在写shell脚本时,经常需要for进行100次循环。for 循环是固定循环,也就是在循环时已经知道需要进行几次循环。有时也把 for 循环称为计数循环。
Shell for循环语法
for 变量 in 列表
do
command1
command2
...
commandN
done
**也可以写成:for var in list; do
读取列表中的值
#!/bin/bash
#basic for command
for 558idc in 自由互联 Linuxmi linux Ubuntu
do
echo The next state is $558idc
done
执行结果:
558idc@558idc:~/558idc.com$ ./558idc.sh
The next state is 自由互联
The next state is Linuxmi
The next state is linux
The next state is Ubuntu
在最后一次迭代后,$558idc变量的值会在shell脚本的剩余部分保持有效。它会一直保持最后一次迭代的值(除非你已经修改了它)。
读取列表中的复杂值
有两种解决办法:
*使用转义字符(反斜线)来将单引号转移;
*使用双引号来定义用到单引号的值。
#!/bin/bash
#basic for command
for 558idc in Kotlin Linuxmi\'com linux Ubuntu "CentOS'rhel" Oracle
do
echo The next state is $558idc
done
执行结果:
558idc@558idc:~/558idc.com$ ./558idc.sh
The next state is Kotlin
The next state is Linuxmi'com
The next state is linux
The next state is Ubuntu
The next state is CentOS'rhel
The next state is Oracle
*记住,for命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。
从变量读取列表
将一系列的值都集中存储在一个变量中,然后需要遍历变量中的整个列表。
#!/bin/bash
#using a variable to hold the list
list="Linuxidc Linuxmi Ubuntu Fedora"
#向已有列表中添加或拼接一个值
list=$list" success"
for state in $list
do
echo "this word is $state"
done
执行结果:
558idc@558idc:~/558idc.com$ ./558idc.sh
this word is Linuxidc
this word is Linuxmi
this word is Ubuntu
this word is Fedora
this word is success
从命令读取值
有两种方式可以将命令输出赋值给变量:
(1)反引号字符(`)
(2)$()格式
例如:
558idc=`date`
558idc=$(date)
生成列表中所需值就是使用命令的输出。
#!/bin/bash
# reading values from a file
file="states"
for state in $(cat $file)
do
echo "welcome $state"
done
states文件内容;
www.558idc.com
Hello World
Linuxmi com
558idc.net 自由互联
执行结果:
558idc@558idc:~/558idc.com$ ./558idc.sh
welcome www.558idc.com
welcome Hello
welcome World
welcome Linuxmi
更改字段分隔符
造成这个问题的原因是特殊的环境变量IFS,叫作内部字段分隔符。默认情况下,bash shell会将下列字符当作字段分隔符:
*空格
*制表符
*换行符
如果bash shell在数据中看到这些字符中的任意一个,它就会假定这表明了列表中一个新数据字段的开始。
想修改IFS的值,使其只能识别换行符,那就必须:
IFS=$'\n'
将这个语句加入到脚本中,告诉bash shell在数据值中忽略空格和制表符。
#!/bin/bash
# reading values from a file
file="states"
IFS=$'\n'
for state in $(cat $file)
do
echo "Welcome $state"
done
执行结果:
Welcome www.558idc.com
Welcome Hello World
Welcome Linuxmi com
Welcome 558idc.net 自由互联
一个可参考的安全实践是在改变IFS之前保存原来的IFS值,之后再恢复它。
实现:
IFS.OLD=$IFS
IFS=$'\n'
<在代码中使用新的IFS值>
IFS=$IFS.OLD
这就保证了在脚本的后续操作中使用的是IFS的默认值。
遍历一个文件中用冒号分隔的值:
IFS=:
如果要指定多个IFS字符,只要将它们在赋值行串起来就行。
IFS=$'\n':;"
这个赋值会将换行符、冒号、分号和双引号作为字段分隔符。如何使用IFS字符解析数据没有任何限制。
用通配符读取目录
#!/bin/bash
for file in /home/558idc/558idc.com/*;
do
echo $file is file path \! ;
done
执行结果:
558idc@558idc:~/558idc.com$ ./558idc.sh
/home/558idc/558idc.com/03.jpg is file path !
/home/558idc/558idc.com/123.jpg is file path !
/home/558idc/558idc.com/123.png is file path !
/home/558idc/558idc.com/2.avi is file path !
/home/558idc/558idc.com/amp is file path !
/home/558idc/558idc.com/atom-amd64.deb is file path !
/home/558idc/558idc.com/car.jpg is file path !
/home/558idc/558idc.com/car.png is file path !
/home/558idc/558idc.com/chenduling.jpg is file path !
/home/558idc/558idc.com/com.testdemo.java is file path !
/home/558idc/558idc.com/DarkPicDir is file path !
/home/558idc/558idc.com/data is file path !
类C风格for循环的语法格式
for((expr1; expr2; expr3))
do
command
command
...
done
有些部分并没有遵循bash shell标准的for命令:
*变量赋值可以有空格
*条件中的变量不以美元符开头
*迭代过程的算式为用expr命令格式
ex9、输出前6个正数
#!/bin/bash
#使用类C风格for循环输出1~6
for ((integer = 1; integer <= 6; integer++))
do
echo "$integer"
done
执行如下:
尽管可以使用多个变量,但你只能在for循环中定义一种条件。
#!/bin/bash
for ((x=1,y=8;x<=8;x++,y--))
do
echo "$x - $y"
done
执行如下:
使用类C风格for循环要注意以下事项:
a.如果循环条件最初的退出状态为非0,则不会执行循环体
b.当执行更新语句时,如果循环条件的退出状态永远为0,则for循环将永远执行下去,从而产生死循环
c.Linux shell中不运行使用非整数类型的数作为循环变量
d.如果循环体中的循环条件被忽略,则默认的退出状态为0
e.在类C风格的for循环中,可以将三个语句全部忽略掉,下面是合法的for循环
#!/bin/bash
for((; ; ))
do
echo "hello world www.558idc.com"
done