[bash]for、while/until、循环控制、循环输出定向和管接

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命令中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值