for 命令
每次 for 命令遍历值列表,它都会将列表中的下个值赋给 $test 变量。 $test 变量可以像 for
命令语句中的其他脚本变量一样使用。在最后一次迭代后, $test 变量的值会在shell脚本的剩余
部分一直保持有效。它会一直保持最后一次迭代的值(除非你修改了它)
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"
for 命令用空格来划分列表中的每个值。如果在单独的数据值中有
空格,就必须用双引号将这些值圈起来
for test in Nevada "New Hampshire" "New Mexico" "New York"
do
echo "Now going to $test"
done
list="Alabama Alaska Arizona Arkansas Colorado"
# 拼接字符串
list=$list" Connecticut"
for state in $list
do
echo "Have you ever visited $state?"
done
# 文件读取
file="states"
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
这个例子在命令替换中使用了 cat 命令来输出文件states的内容。你会注意到states文件中每一
行有一个州,而不是通过空格分隔的。 for 命令仍然以每次一行的方式遍历了 cat 命令的输出,
假定每个州都是在单独的一行上。但这并没有解决数据中有空格的问题。如果你列出了一个名字
中有空格的州, for 命令仍然会将每个单词当作单独的值
更改字段分隔符
造成这个问题的原因是特殊的环境变量 IFS ,叫作内部字段分隔符(internal field separator)。
IFS 环境变量定义了bash shell用作字段分隔符的一系列字符。默认情况下,bash shell会将下列字
符当作字段分隔符:
空格
制表符
换行符
如果bash shell在数据中看到了这些字符中的任意一个,它就会假定这表明了列表中一个新数
据字段的开始。在处理可能含有空格的数据(比如文件名)时,这会非常麻烦,就像你在上一个
脚本示例中看到的。
要解决这个问题,可以在shell脚本中临时更改 IFS 环境变量的值来限制被bash shell当作字段
分隔符的字符。例如,如果你想修改 IFS 的值,使其只能识别换行符,那就必须这么做:
IFS=$'\n'
将这个语句加入到脚本中,告诉bash shell在数据值中忽略空格和制表符
file="states"
IFS=$'\n'
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
在处理代码量较大的脚本时,可能在一个地方需要修改 IFS 的值,然后忽略这次修改,在
脚本的其他地方继续沿用 IFS 的默认值。一个可参考的安全实践是在改变 IFS 之前保存原
来的 IFS 值,之后再恢复它。
这种技术可以这样实现:
IFS.OLD=$IFS
IFS=$'\n'
<在代码中使用新的IFS值>
IFS=$IFS.OLD
这就保证了在脚本的后续操作中使用的是 IFS 的默认值
用通配符读取目录
for file in /home/*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
for (( i=1; i <= 10; i++ ))
do
echo "The next number is $i"
done
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done