更多结构化命令 for啥的

本文深入讲解Bash脚本中的各种循环结构,包括基本for循环、C风格for循环、while循环和until循环等,并演示如何使用这些循环进行文件操作、变量处理及嵌套循环等常见任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重复执行某一些命令:

for var in list

do

    commands

done

当然,还有一种形式:

for var in list ; do

这样,do与for就在同一行了。


其中list里是一些需要迭代的值

而var会依次迭代list中的值

如何访问呢?使用$var  


[oh@localhost shell]$ cat for1
#!/bin/bash
#basic for command

for test in albama alaska arizona arkansas california colorado
do 
	echo the next state is $test
done


[oh@localhost shell]$ ./for1
the next state is albama
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
[oh@localhost shell]$ 

在同一行的话:done也是要写的

[oh@localhost shell]$ cat for1
#!/bin/bash
#basic for command

for test in albama alaska arizona arkansas california colorado;do

	echo the next state is $test
done


[oh@localhost shell]$ ./for1
the next state is albama
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
是的,在我赋值时,=号后是不能有空格的,这还真是难啊
[oh@localhost shell]$ cat -n for1
     1	#!/bin/bash
     2	#basic for command
     3	
     4	for test in albama alaska arizona arkansas california colorado;do
     5	
     6		echo the next state is $test
     7	done
     8	echo "the last state we visited was $test"
     9	$test = connecticut
    10	echo "wait,now we're visiting $test"
    11	
    12	
    13	
[oh@localhost shell]$ vim for1
[oh@localhost shell]$ cat for1
#!/bin/bash
#basic for command

for test in albama 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"



[oh@localhost shell]$ ./for1
the next state is albama
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
./for1: line 9: colorado: command not found
wait,now we're visiting colorado
[oh@localhost shell]$ cat -n for1
     1	#!/bin/bash
     2	#basic for command
     3	
     4	for test in albama alaska arizona arkansas california colorado;do
     5	
     6		echo the next state is $test
     7	done
     8	echo "the last state we visited was $test"
     9	$test = 'connecticut'
    10	echo "wait,now we're visiting $test"
    11	
    12	
    13	
[oh@localhost shell]$ vim for1
[oh@localhost shell]$ ./for1
the next state is albama
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
./for1: line 9: test: =: unary operator expected
wait,now we're visiting colorado
[oh@localhost shell]$ vim for1
[oh@localhost shell]$ ./for1
the next state is albama
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
[oh@localhost shell]$ cat for1
#!/bin/bash
#basic for command

for test in albama 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"



[oh@localhost shell]$ vim for1
[oh@localhost shell]$ ./for1
the next state is albama
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
./for1: line 10: connecticut: command not found
wait,now we're visiting colorado
[oh@localhost shell]$ cat for1
#!/bin/bash
#basic for command

for test in albama 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"



[oh@localhost shell]$ 

当list是包含单引号的语句时,情况就有些不对了。

[oh@localhost shell]$ cat -n for2
     1	#!/bin/bash
     2	#another example for how to use the for command
     3	
     4	for test in I don't know if this'll work
     5	do
     6		echo "word:$test"
     7	done
     8	
     9	
[oh@localhost shell]$ ./for2
word:I
word:dont know if thisll
word:work

shell看到了列表中的单引号并尝试使用他们来定义一个单独的数据值。

解决办法:\来转意  或是用“”引起来

[oh@localhost shell]$ cat -n for2
     1	#!/bin/bash
     2	#another example for how to use the for command
     3	
     4	for test in I don\'t know if "this'll" work
     5	do
     6		echo "word:$test"
     7	done
     8	
     9	
[oh@localhost shell]$ ./for2
word:I
word:don't
word:know
word:if
word:this'll
word:work
[oh@localhost shell]$ 

for命令用空格来划分列表中的值,所以有时需要用到 “  ” 号来输出空格:

[oh@localhost shell]$ cat -n for2
     1	#!/bin/bash
     2	#another example for how to use the for command
     3	
     4	for test in I don\'t know if "this'll" work "i'm ok" "going to NewYork"
     5	do
     6		echo "word:$test"
     7	done
     8	
     9	
[oh@localhost shell]$ ./for2
word:I
word:don't
word:know
word:if
word:this'll
word:work
word:i'm ok
word:going to NewYork
当你在某个值的两边使用双引号时,shell不会将双引号当成值得一部分。

---

从变量读取列表:

当你将一系列值存储在变量中,for也能遍历它:

[oh@localhost shell]$ ./for2
word:alaba
word:alaska
word:arizona
word:arkansas
word:colorado
word:Connect
[oh@localhost shell]$ cat -n for2
     1	#!/bin/bash
     2	#another example for how to use the for command
     3	
     4	#for test in I don\'t know if "this'll" work "i'm ok" "going to NewYork"
     5	list="alaba alaska arizona arkansas colorado"
     6	list=$list" Connect"  //在变量中的尾部添加文本的常用方法
     7	for state in $list
     8	do
     9		echo "word:$state"
    10	done
    11	
    12	

---------

从命令里读取值:

利用命令的输出,反引号扩起来`   `

[oh@localhost shell]$ cat for3
#!/bin/bash
#reading values from a file

file="states"

for state in `date`
do 
	echo "now is $state"
done

[oh@localhost shell]$ ./for3
now is Sat
now is Mar
now is 31
now is 20:04:14
now is CST
now is 2018

--------

更改字段分隔符:

默认情况下,空格,制表符,换行符会被当成分隔符,因为

有一个环境变量:IFS(internal field separator)内部字段分隔符里定义了

[oh@localhost shell]$ cat for2
#!/bin/bash
#another example for how to use the for command

#for test in I don\'t know if "this'll" work "i'm ok" "going to NewYork"
list="alaba alaska arizona arkansas colorado"
list=$list" Connect"
for state in $list
do
	echo "word:$state"
done


[oh@localhost shell]$ cat -n for3
     1	#!/bin/bash
     2	#reading values from a file
     3	
     4	file="states"
     5	
     6	for state in `cat for1`
     7	do 
     8		echo "now is $state"
     9	done
    10	
[oh@localhost shell]$ ./for3
now is #!/bin/bash
now is #basic
now is for
now is command
now is for
now is test
now is in
now is albama
now is alaska
now is arizona
now is arkansas
now is california
now is colorado
now is do
now is echo
now is the
now is next
now is state
now is is
now is $test
now is done
now is echo
now is "the
now is last
now is state
now is we
now is visited
now is was
now is $test"
now is test=
now is connecticut
now is echo
now is "wait,now
now is we're
now is visiting
now is $test"
[oh@localhost shell]$ 

如果你只想使用换行符来分隔的话:必须改变一下IFS变量

IFS=$'\n'

这样就会在数据中忽略空格跟制表符


[oh@localhost shell]$ cat -n for3
     1	#!/bin/bash
     2	#reading values from a file
     3	
     4	file="states"
     5	IFS=$'\n'
     6	for state in `cat for1`
     7	do 
     8		echo "now is $state"
     9	done
    10	
[oh@localhost shell]$ ./for3
now is #!/bin/bash
now is #basic for command
now is for test in albama alaska arizona arkansas california colorado
now is do
now is 	echo the next state is $test
now is done
now is echo "the last state we visited was $test"
now is test= connecticut
now is echo "wait,now we're visiting $test"

那么当我  用 IFS='\n'时:就是\  与 n  作为分隔符了

[oh@localhost shell]$ cat -n for3
     1	#!/bin/bash
     2	#reading values from a file
     3	
     4	file="states"
     5	IFS='\n'
     6	for state in `cat for1`
     7	do 
     8		echo "now is $state"
     9	done
    10	
[oh@localhost shell]$ ./for3
now is #!/bi
now is /bash
#basic for comma
now is d

for test i
now is  albama alaska arizo
now is a arka
now is sas califor
now is ia colorado
do

	echo the 
now is ext state is $test
do
now is e
echo "the last state we visited was $test"
test= co
now is 
now is ecticut
echo "wait,
now is ow we're visiti
now is g $test"
[oh@localhost shell]$ 

那么要使用冒号:时   IFS=:

也就是说,要    \n  这种需要转义的字符才要用$

IFS=$'\n:;'"    就是换行,冒号,分号及双引号作分隔符了


而当你要恢复IFS时,就得先保存它,

IFS.OLD=$IFS

IFS=$'\n'

.....

.....

IFS=$IFS.OLD  //这样就恢复了


========

用通配符读取目录: 用for命令来自动遍历满是文件的目录。则你必须在文件名或是路径名中使用通配符。它会强制shell使用文件扩展匹配(file globbing),它是生成匹配指定的通配符的文件名或路径名的过程

[oh@localhost shell]$ cat -n for5
     1	#!/bin/bash
     2	#iterate through all the files in a directory
     3	
     4	for file in /home/oh/linux/git/*
     5	do
     6		if [ -d "$file" ]
     7		then
     8		  echo "$file is a directory"
     9		elif [ -f "$file" ]
    10		then
    11		  echo "$file is a file"
    12		fi
    13	done
    14	
    15	
[oh@localhost shell]$ ./for5
/home/oh/linux/git/manlist is a directory
/home/oh/linux/git/mylog is a directory
/home/oh/linux/git/py is a directory

虽然不是递归巡查

之所以要双引号 “$file” 是因为如果其中有空格的话,会出现:

too many arguments 的错误


[oh@localhost shell]$ cat -n for5
     1	#!/bin/bash
     2	#iterate through all the files in a directory
     3	
     4	for file in /home/oh/linux/git/* /home/oh/l*
     5	do
     6		if [ -d "$file" ]
     7		then
     8		  echo "$file is a directory"
     9		elif [ -f "$file" ]
    10		then
    11		  echo "$file is a file"
    12		fi
    13	done
    14	
    15	
[oh@localhost shell]$ ./for5
/home/oh/linux/git/manlist is a directory
/home/oh/linux/git/mylog is a directory
/home/oh/linux/git/py is a directory
/home/oh/libflashplayer.so is a file
/home/oh/license.pdf is a file
/home/oh/linux is a directory
[oh@localhost shell]$ 

------------------

C语言风格的for命令:

for(( a = 1; a < 10 ; a++ ))

注意:有一些事情没有遵循标准的bash shell for 命令:

1.变量赋值可以有空格

2.条件变量不以美元符开头

3.迭代过程的算式未用expr格式

[oh@localhost shell]$ cat -n for6
     1	#!/bin/bash
     2	#testing the C-style for loop
     3	for (( i=1;i <=10;i++ ))
     4	do
     5		echo "the next number is $i"
     6	done
     7	
     8	
[oh@localhost shell]$ ./for6
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

使用多个变量:

[oh@localhost shell]$ cat -n for6
     1	#!/bin/bash
     2	#testing the C-style for loop
     3	for (( i=1,b=0;i <=10;i++,b++ ))
     4	do
     5		echo $b
     6		echo "the next number is $i"
     7	done
     8	
     9	
[oh@localhost shell]$ ./for6
0
the next number is 1
1
the next number is 2
2
the next number is 3
3
the next number is 4
4
the next number is 5
5
the next number is 6
6
the next number is 7
7
the next number is 8
8
the next number is 9
9
the next number is 10
[oh@localhost shell]$ 


---------------------

while命令:

while test command

do

 other commands

done

注意test command 的退出状态码必须随着运行中的环境变量而改变

不变的话很可能会有死循环

比如这样:

[oh@localhost shell]$ cat -n for7
     1	#!/bin/bash
     2	#while command test
     3	
     4	var1=10
     5	while [ $var1-1 ]
     6	do
     7	   echo $var1
     8	   var1=$[ $var1 - 1 ]
     9	done
    10	
[oh@localhost shell]$ ./for7
10
9
8
7
6
5
4
3
2
1
0
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
[oh@localhost shell]$ cat -n for7
     1	#!/bin/bash
     2	#while command test
     3	
     4	var1=10
     5	while [ $var1 -gt 1 ]
     6	do
     7	   echo $var1
     8	   var1=$[ $var1 -1 ]
     9	done
    10	
[oh@localhost shell]$ ./for7
10
9
8
7
6
5
4
3
2
[oh@localhost shell]$ 
使用多个测试命令:

最后一个测试命令的退出状态码用来决定作不做下面的循环体:

[oh@localhost shell]$ cat for8
#!/bin/bash
#testing a multicommand whil loop

var1=10

while echo $var1
	[ $var1 -ge 0 ]
do
	echo "this is inside the loop"
	var1=$[ $var1 - 1 ]
done


[oh@localhost shell]$ ./for8
10
this is inside the loop
9
this is inside the loop
8
this is inside the loop
7
this is inside the loop
6
this is inside the loop
5
this is inside the loop
4
this is inside the loop
3
this is inside the loop
2
this is inside the loop
1
this is inside the loop
0
this is inside the loop
-1
[oh@localhost shell]$ 

---------------

util命令:

其工作方式与while刚好相反,指定的命令退出状态码为0时,退出循环,只有在非0时才执行循环体。


util test commands

do

    other commands

done

[oh@localhost shell]$ cat util
#!/bin/bash
#using the until command

var=100

until [ $var -eq 0 ]
do
	echo $var
	var=$[ $var - 25 ]
done


[oh@localhost shell]$ ./util
100
75
50
25
[oh@localhost shell]$ 

你也可以使用多个测试命令:

[oh@localhost shell]$ cat util
#!/bin/bash
#using the until command

var=100

until   echo $var 
	[ $var -eq 0 ]
do
	echo Inside the loop: $var
	var=$[ $var - 25 ]
done


[oh@localhost shell]$ ./util
100
Inside the loop: 100
75
Inside the loop: 75
50
Inside the loop: 50
25
Inside the loop: 25
0
[oh@localhost shell]$ 

-----

嵌套循环:

循环里有循环:(nestedloop)或是混用循环

[oh@localhost shell]$ cat -n qt
     1	#!/bin/bash
     2	#testing for loops
     3	
     4	for (( a = 1;a<=3;a++ ))
     5	do
     6		echo "starting loop:$a:"
     7		for (( b=1;b<=3;b++ ))
     8		do
     9		  echo "  inside loop:$b"
    10		done
    11	done
    12	
    13	
[oh@localhost shell]$ ./qt
starting loop:1:
  inside loop:1
  inside loop:2
  inside loop:3
starting loop:2:
  inside loop:1
  inside loop:2
  inside loop:3
starting loop:3:
  inside loop:1
  inside loop:2
  inside loop:3
[oh@localhost shell]$ 

---------

循环处理文件数据:

需要使用两种技术:

  1,嵌套循环

  2,修改IFS变量

一般是得到文件中的每一行的数据

再次循环来得到其中的数据

经典例子是 /etc/passed里的数据

需要将IFS的值改成:号

[oh@localhost shell]$ cat eg
#!/bin/bash
#changing the IFS value

IFS.OLD=$IFS
IFS=$'\n'
for entry in `cat /etc/passwd`
do
	echo "values in $entry- "
	IFS=:
	for value in $entry
	do
		echo " $value"
	done
done


[oh@localhost shell]$ ./eg
./eg: line 4: IFS.OLD=: command not found
values in root:x:0:0:root:/root:/bin/bash- 
 root
 x
 0
 0
 root
 /root
 /bin/bash
values in bin:x:1:1:bin:/bin:/sbin/nologin- 
 bin
 x
 1
 1
 bin
 /bin
 /sbin/nologin
values in daemon:x:2:2:daemon:/sbin:/sbin/nologin- 
 daemon

得到好多的这类信息


控制循环:break  continue


break:   

跳出单个循环  

跳出里面的循环

跳出外部循环,这个要指定个参数   break n   默认情况下n为1    为2的话,就会去停止包裹其的循环


continue   提早结束本次语句组,但是没有结束循环  类似于C语言里的continue

也有 continue n


=========

处理循环的输出:

要么接管,要么重定向输出

在done的后面

done > output.txt

或是

done | sort
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值