1. for命令列表中的元素使用空格分隔:
#!/bin/bash
for x in 1 2 3 4 5 6 7 8 #bash默认用空格来分隔迭代值,注意,即使是数字但仍然是字符串
do
echo $x
done
echo $x #保留迭代的最后一个值
for s in abc bca kk dd sldkfjs
do
echo $s
done
2. 处理列表元素中的特殊字符(即解析复杂的迭代值):
#!/bin/bash
for w in I don\'t know if "this'll" work #如果迭代值出现',则使用转义或者""括起来都行
do
echo $w
done
for p in "Xi'an" "Chang sha" Nevada "New York" #如果迭代值本身还有空格,则使用""将迭代值括起来
do
echo I wanna go to $p
done
#总体来说建议同意使用"",看起来更加直观并且方便调试
3. 从变量中获取列表:
#!/bin/bash
s="sdf kkk sdfjskdljf skldfjwoei"
s=$s" ppppp" #""实际上就是一个构造字符串字面值的运算符,会将括号中的内容作为字符串替换到当前位置,也是一种宏
for x in $s
do
echo $x
done
如果直接以字符串变量作为迭代对象,则将以字符串中的空白符作为分隔符!比如:
s=“a b c d”
for w in $s
do
echo $w
done
//output
a
b
c
d
for w in $s $s
do
echo $w
done
//output
a
b
c
d
a
b
c
d
4. 从命令中获取列表:
!这种方式同样也是将命令的结果作为一整个字符串看待,所以和上面的例子一样,这种方式下同样是把空白符作为分隔符:
#!/bin/bash
for x in `cat ./test.txt`
do
echo $x
done
#./test.txt
kkkk
aaaaa
dsfffffdfs
xzxvadsf
bbbbb<span style="white-space:pre"> </span>#以空白符作为迭代值的分隔符,若干连续的多个空白符(' '、\t、\n)都会当做一个空白符
skdfjwsdfkw
dddd vvvvv
sdf'sdfkwef<span style="white-space:pre"> </span>#由于不是shell源代码文本可以随意使用'和"而无需转义,这是显而易见的!
bskdf"sdkf"
#输出
kkkk
aaaaa
dsfffffdfs
xzxvadsf
bbbbb
skdfjwsdfkw
dddd
vvvvv
sdf'sdfkwef
bskdf"sdkf"
5. 修改列表解析的分隔符(使用的文件仍然是4.中的./test.txt):
#!/bin/bash
#Internal Field Separator
#内部字段分隔符,用于解析列表的分隔符
#默认值是' '、\t、\n
#值保存在环境变量$IFS中
#用户可以在同一个脚本中任意修改,退出脚本后就恢复成了默认值
#修改方式为IFS=$'...'
#分隔符可以设置多个,修改时直接连接即可,比如:IFS=$',\n\t:'
#这里分隔符有, \n \t和:
#在解析/etc/passwd文件时用:作为分隔符就比较好!
IFSOLD=$IFS #先保存默认值,以便在用完之后可以恢复
IFS=$'\n' #修改成\n
for x in `cat ./test.txt`
do
echo $x
done
IFS=$IFSOLD #恢复成默认值,在接下里的程序中可以使用
for x in `cat ./test.txt`
do
echo $x
done
echo $IFS
#第一个测例的输出:
aaa
dsfffffdfs
xzxvadsf
bbbbb
skdfjwsdfkw
dddd vvvvv
sdf'sdfkwef
bskdf"sdkf"
#第二个测例的输出
aaaa
dsfffffdfs
xzxvadsf
bbbbb
skdfjwsdfkw
dddd
vvvvv
sdf'sdfkwef
bskdf"sdkf"
6. 使用空白符获取列表:
#!/bin/bash
for file in $HOME/* #使用通配符获取列表
do
if [ -d "$file" ] #Linux是允许文件名含有空格的,$仅仅是一个宏替换,如果含有空格则test命令会将其作为多个参数而不是一个参数处理而报错,因此必须使用""将其作为一个字符串处理
then
echo "directory: $file"
elif [ -f "$file" ]
then
echo "file : $file" #echo打印字符串时以多个连续的空白符作为一个空格处理,因此需要用""来打印多个连续的空格!!!
fi
done
7. 多种方式合并使用来获取列表:
#!/bin/bash
for str in `cat test.txt` $HOME/* lllllqqqqqqq #代码中还是以空格作为分隔符即可
do
echo $str
done
8. C风格的for——for (( )):
#!/bin/bash
for ((i = 10; i; i--)) #空格可以随意加,并且在(())中引用变量时不需要$运算符,完全跟C语言一样
do
echo $i #一旦出了(())就得使用$引用变量了
done
for (( a = 1, b = 10; a <= 5 && b >= 7; a++, b-- )) #可以迭代多个值,和C语言一模一样
do
echo $a - $b
echo $[ $a + $b ]
done
9. 类似C语言逗号表达式的while多条件测试:
#!/bin/bash
v=10
while echo $v #多测试命令类似C语言的逗号表达式,每条命令占一行(否则会报错!!)
echo $v!! #多条件测试和C语言的逗号表达式一样主要用于产生副作用
[ $v -ge 0 ] #只有最后一条命令作为循环的判断条件
do
echo This is in the loop
v=$[ $v - 1 ]
done
10. until循环:
#!/bin/bash
v=100
until [ $v -eq 0 ] #知道条件成立才停止循环
do
echo $v
v=$[ $v - 25 ]
done
v=100
until echo $v #until也支持多条件测试
[ $v -eq 0 ]
do
echo Inside the loop
(( v = $v - 25 ))
done
11. 循环嵌套:
#!/bin/bash
for (( i = 1; i <= 3; i++ ))
do
echo Starting loop $i:
for (( j = 1; j <= 3; j++ ))
do
echo Inside loop $j
done
done
i=5
while [ $i -ge 0 ]
do
echo Outer loop $i:
for (( j = 1; j <= 3; j++ ))
do
echo "Inner loop: $i * $j = $[ $i * $j ]" #*会被bash理解成通配符,所以需要用""括起来表示一个普通字符
done
i=$[ $i - 1 ]
done
i=3
until [ $i -eq 0 ]
do
echo Outer loop $i:
j=1
while [ $j -lt 5 ]
do
v=`echo "scale = 4; $i / $j" | bc`
echo "Inner loop: $i / $j = $v"
j=$[ $j + 1 ]
done
i=$[ $i - 1 ]
done
12. 利用IFS和循环嵌套解析/etc/passwd中的内容:
#!/bin/bash
IFS=$'\n' #使用$''的形式在脚本中的当前位置彻底改变IFS的值,但是退出脚本后就恢复成默认值
for entry in `cat /etc/passwd`
do
#环境变量也是有作用域的
IFS=: #在代码块中直接赋值只能临时改变IFS的值,出了这个代码块该值就无效并恢复成进入代码块之前的值
echo Valuse in $entry are:
for val in $entry
do
echo " $val"
done
done
!注意:当用单引号' '引起字符串时不会将$XXX解析成提取变量的内容而是直接当成普通字符串看待,而双引号" "则会解析字符串中的特殊符号,比如:
echo '$HOME'会直接打印出$HOME这个字符串,而echo "$HOME"则会打印出用户的主目录的绝对路径!
13. break命令:
#!/bin/bash
for v in 1 2 3 4 5 6 7 8 9
do
if [ $v -eq 5 ]
then
break #不带参数默认为跳出当前最近的一层循环,默认参数为1,表示当前的最近1层循环
fi
echo Iteration number: $v
done
echo Complete!
v=1
while [ $v -lt 10 ]
do
if [ $v -eq 5 ]
then
break
fi
echo Iteration number: $v
v=$[ $v + 1 ]
done
echo Complete!
#跳出内存循环
for (( i = 1; i < 4; i++ ))
do
echo Outer loop: $i
for (( j = 1; j < 100; j++ ))
do
if [ $j -eq 5 ]
then
break
fi
echo Inner loop: $j
done
done
echo Complete!
#跳出外层循环
for (( i = 1; i < 4; i++ ))
do
echo Outer loop: $i
for (( j = 1; j < 100; j++ ))
do
if [ $j -gt 4 ]
then
break 2 #向外跳出两层循环,如果没有参数则默认为1,即当前最近的循环
fi
echo " Inner loop: $j"
done
done
echo Complete!
14. continue命令(和break命令用法一样):
#!/bin/bash
for (( i = 1; i < 15; i++ ))
do
if [ $i -gt 5 ] && [ $i -lt 10 ]
then
continue
fi
echo Iteration number: $i
done
echo Complete!
i=0
while echo "while iteration: $i"
[ $i -lt 15 ]
do
if [ $i -gt 5 ] && [ $i -lt 10 ]
then
i=$[ $i + 1 ] #注意!
continue
fi
echo " Inside iteration number: $i"
i=$[ $i + 1 ]
done
for (( i = 1; i < 10; i++ ))
do
echo Iteration $i:
for (( j = 1; j < 3; j++ ))
do
if (( 2 < i && i < 6 ))
then
continue 2
fi
echo " The result of $i * $j = $[ $i * $j ]"
done
done
15. 循环重定向和管接:
#!/bin/bash
for file in $HOME/*
do
if [ -d "$file" ]
then
echo $file is a directory
else
echo $file is file
fi
done > t1.out #将循环的所有echo输出按顺序重定向到指定文件中
for (( i = 1; i < 10; i++ ))
do
echo $i
done > t2.out
for state in sfdf aaaa kjsdkf zzflef klsafj
do
echo $state
done | sort #将循环echo管接至sort命令中