第七章 Bash循环

shell可以重复地执行特定的指令,直到特定的条件被满足为止。这重复执行的一组命令就叫做循环。
每一个循环都具有以下特点:

  • 首先,循环条件中使用的变量必须是已初始化的,然后在循环中开始执行。
  • 在每一次循环开始时进行一次测试。
  • 重复的执行一个代码块

7.1 for循环

7.1.1  for循环语法

for循环的基本语法:

for VAR in item1 item2 ... item
do
  command1
  command2
  ...
  ...
  commandN
done

for循环变量的内容的语法:

for VAR in $fileNames
do
  command1
  command2
  ...
  ...
  commandN
done

for循环命令替换的语法:

for VAR in $(Linux-command-name)		#或者使用: for VAR in `Linux-command-name`
do
  command1
  command2
  ...
  ...
  commandN
done

for循环还有三项表达式语法,这种语法与C语言中常见for循环使用方法相同。
for循环三项表达式语法:

for  (( EXP1; EXP2; EXP3 ))
do
  command1
  command2
  ...
  ...
  commandN
done

上述语法以三项参数循环控制表达式为特征,它由一个初始化式(EXP1)、循环测试或条件(EXP2)和一个计算表达式(EXP3)组成。
在for循环中,每次指定列表中的(iterm1…itermN)新值被赋给变量VAR后,for循环都会执行一次,它将重复运行‘do’和‘done’之间的所有语句,直到条件不满足时为止。这些列表或数值通常是:

  • 字符串
  • 数字
  • 命令行
  • 参数
  • 文件名
  • Linux命令的输出

我们来看一个简单的for循环的脚本:

#!/bin/bash

for i in 1 2 3 # 从1~3循环
do
	echo "The for loop is run $i times"
done

接下来看一个字符串的循环示例:

#! /bin/bash

for linux in Debin Redhat Suse Fedora
do
	echo "The OS is : $linux"
done

使用变量内容的for循环示例:

#! /bin/bash

filenames="/etc/yp.conf /etc/nsswitch.sh /etc/auto.master /etc/resolv.conf" # 文件名以空格分隔
for file in $filenames
do
	[ -f $file ] && echo "The file $file was found" || echo "*** Error : The file $file was missing. ***"
done

使用命令替换的for循环实例:

#! /bin/bash

echo "Printing file list in /tmp/directory:"
for file in 'ls /tmp/*'
do
	echo $file
done

7.1.2 嵌套for循环语句

嵌套循环的意思即是在循环中循环。下面我们看一个简单的嵌套for循环的实例:

#! /bin/bash

for (( i = 0; i < 3; i++ ))
do
	for(( j = 0; j < 5; j++ ))
  do
    echo -n "* "
  done
	echo ""
done

那么脚本运行后的结果类似如下所示:

$ chomd =x simplenestedfor.sh
$ ./simplenestedfor.sh
* * * * *
* * * * *
* * * * *

7.2 while循环

while循环语法用于重复执行一个命令列表。

7.2.1 while循环语法

while循环语句的语法:

while [ CONDITION ]
do
	command1
	command2
	…
	...
	commandN
done

当条件CONDITION为真时,command1 … commandN将被执行。例如逐行地读取一个文本文件的内容,其语法类似如下:

while IFS= read -r line
do
	command1 on $line
	command2 on $line
	... 
	.....
	commandN
done < "/path/to/file"

我们看一个简单的使用while循环的实例

#! /bin/bash

var=1
while [ $var -le 3 ]
do
	echo "The for loop is run $var times."
	var=$(( var + 1 ))

done

运行结果如下:

$ chomd +x whileloop.sh
$ ./whileloop.sh
The for loop is run 1 times
The for loop is run 2 times
The for loop is run 3 times

我们可以将read命令和while循环结合使用来读取一个文本文件:

#!/bin/bash

file=$1
if [ $# -lt 1 ]; then
	echo "Uasge: $0 FILEPATH"
	exit
fi

while read -r line
do
	echo $line
done < "$file"

执行该文件:

bash whichereadfile.sh file

还可以按列读取文件的内容,如下脚本在上述脚本的基础上将文件分为3列输出:

#!/bin/bash

file=$1
if [ $# -lt 1 ]; then
	echo "Uasge: $0 FILEPATH"
	exit
fi

while read -r f1 f2 f3
do
	echo "Field 1: $f1 ===> Field 2: $f2 ===> Field 3: $f3"
done < "$file"

7.2.2定义无限while循环

你可以将while循环和专用命令“:”结合使用来定义一个无限循环。在几种情况下,这是一个期望的行为。例如,菜单驱动程序通常持续运行到用户选择退出主菜单(循环)。由于循环固有的一些特性,当条件永远不被满足时,也会发生一个无限循环。定义一个无限while循环可以使用如下三种命令:

  • true命令 - 不做任何事,表示成功,总是返回退出状态码0。
  • false命令 - 不做任何事,表示成功,总是返回退出状态码1。
  • :命令 – 无作用,此命令也不做任何事,总是返回退出状态码。

使用":"命令定义一个无限循环:

#! /bin/bash

while :
do
	echo "Do something..."
	echo "Hit [ CTRL+C ] to stop!"
	sleep 3
done

注意: ":"命令是Bash的内部命令。

使用true命令定义一个无限循环:

#! /bin/bash
while true
do
	echo "Do something..."
	echo "Hite [ CTRL+C ] to stop!"
	sleep 3
done

使用false命令定义一个无限循环的语法和使用true命令或“:”命令的语法相似,只需将上述脚本中的true替换为false即可,它们的运行结果相同。
下面是一个菜单驱动程序,它将持续地运行,直到用户按下“4”选择退出为止,下面是实例

#! /bin/bash

while :
do
	clear #清理终端屏幕
	echo "1. Display date and time."
	echo "2. Display system information." 
	echo "3. Display what users are doing." 
	echo "4. Exit"

	read -p "Enter your choice [1-4 ]: " choice #从标准输入中读取用户的输入,并赋值给变量choice 

	case $choice in
  	1)
  		echo "Today is $(date +%Y-%m-%d.)" #打印当前日期,格式为“YYYY-MM-DD”
  		echo "Current time: $(date +%H:%M:%S)" #打印当前时间,格式为“hh:mm:ss”
  		read -p "Press [Enter] key to continue..." readEnterKey  #只读入回车换行符
  		;;
  	2)
  		uname -a #打印系统信息 
  		read -p "Press [Enter] key to continue..." readEnterKey
      ;;
  	3)
  		w #显示系统中当前登录的用户,及用户当前运行的命令 
  		read -p "Press [Enter] key to continue..." readEnterKey
  		;;
  	4)
  		echo "Bye!"
  		exit 0
  		;;
  	*)
  		echo "Error: Invalid option!"
  		read -p "Press [Enter] key to continue..." readEnterKey
  		;;
	esac
done

结果如下:

===========
MAIN - MENU
===========
1.Display date and time.
2.Display system information.
3.Display what users are doing.
4.Exit
Enter your choice [ 1-4 ]: 1 
Today is 2013-10-31. 
Current time:16:43:42
Press [Enter] key to continue...

7.3until循环语法

until循环与while循环类似,也同样基于一个条件。但until循环的判断条件正好与while循环的判断条件相反,until循环在条件为假的情况下才会持续地运行。一旦条件被满足,即为真,就会退出循环。until循环的语法如下所示:

until [ CONDITION ]
do
  command1
  command2
  …
  …
  command
done

until循环与while循环相比:

  • until循环执行直到返回0状态。
  • while循环执行直到返回非0 状态。
  • until循环总是执行至少一次。

下面看一个until循环的实例:

#!/bin/bash

var=1

until [ $var -gt 3 ]
do
	echo "the for loop is run $var times."
	var=$(( var + 1 ))
done

脚本结果如下:

$chmod +x untilloop.sh
$./untilloop.sh
The for loop is run 1 times.
The for loop is run 2 times.
The for loop is run 3 times.

7.4 select循环语法

Bash还提供select循环。其语法如下所示:

select VAR in LIST
do
  command1
  command2
  ...
  ...
  commandN
done

select循环语句具有如下特点:

  • select语句使用Bash内部变量PS3的值作为它的提示符信息。
  • 打印到屏幕上的列表LIST中的每一项会在前面加上一个数字编号。
  • 当用户输入的数字与某一个数字编号一致时,列表中相应的项即被赋予给变量VAR。
  • 如果用户输入的为空,将重新显示列表LIST中的项和提示符信息。
  • 可以通过添加一个退出选项,或输入CTRL+C或CTRL+D退出select循环。

下面我们看一个实例:

#! /bin/bash

PS3="Run command:" #定义 PS3 提示符
select choice in date w hostname "uname -a" Exit #指定select循环的列表
do
	case $choice in
		date) 
      echo "=================================="
      echo "Current system date and time: "
      echo "=================================="
      $choice #直接将变量的值作为命令运行
      ;;
		w) 
      echo "=================================="
      echo "Who is logged on and what they are doing:" 
      echo "=================================="
      $choice 
      ;; 
		hostname)
      echo "=================================="
      echo "Hostname:"
      echo "=================================="
      $choice
      ;;
    "uname -a")
      echo "=================================="
      echo "System information:"
      echo "=================================="
      $choice
      ;;
		Exit)
      echo "Bye!"
      exit 0
      ;;
	esac
done

结果如下:

chmod -x selectloop.sh 
./selectloop.sh
date
w
hostname
uname -a
Exit
Run command:1
====================
Current system date and time: 
====================
Fri Nov 1 18:40:36 CST 2013
Run command:
date
w
hostname
uname -a 
Exit
Run command:4
==============
System information:
==============
Linux localhost 2.6.18-238.9.1.e15PAE #1 SMP Tue Apr 12 19:28:32 EDT 2011
Run command:5
Bye!

7.5 循环控制

break和continue是Bash中的循环控制命令,其用法与其他编程语言中的同名语句完全一致。

7.5.1break语句

break语句用于从for、while、until或select循环中退出,停止循环的执行。
break语句的语法如下所示:

break [n]

n代表嵌套循环的层级,如果指定了n,break将退出n级嵌套循环。如果没有指定n或n不大于等于1,则退出状态码为0,否则退出状态码为n。
下面看一个实例:

#! /bin/bash

# 如果未指定参数,则打印脚本的使用方法,并返回退出状态码1
[ $# -eq 0 ] && { echo "Usage: $0 filepath"; exit 1; }

#将位置参数1的值赋给变量match
match=$1
found=0

#遍历目录/etc下的所以文件
for file in /etc/*
do

  #如果文件的路径与指定的参数文件路径相匹配,则打印文件已找到,并退出for循环
  if [ $file == "$match" ]
  then

    echo "The file $match was found!"
    found=1
    #使用break命令退出for循环
    break

  fi
done


[ $found -ne 1 ] && echo "The file $match not found in /etc directory."

此脚本的运行结果将类似如下所示:

$ chmod +x forbreak.sh
$ ./forbreak.sh /etc/inittab
The file /etc/inittab was found!
$ ./forbraek.sh /etc/host
The file /etc/host not found in /etc directory.

使用break n 语句退出嵌套循环:

#! /bin/bash

# 如果未指定参数,则打印脚本的使用方法,并返回退出状态码 1
[ $# -eq 0 ] && { echo "Usage: $0 command"; exit 1; }

#将位置参数1的值赋给变量match
match=$1
found=0

for dir in /bin /usr/bin
do

  # 遍历目录下的所有文件	
  for file in $dir/*
  do
  
    # 如果文件名与指定的参数文件名相匹配,则打印命令已找到,并退出嵌套的for循环
      if [ $(basename $file) == "$match" ]
      then
      
        echo "The command $match was found!"
        found=1
        # 退出两层的for循环
        break 2
      
      fi
  done

done

[ $found -ne 1 ] && echo "The command $match not found."

7.5.2continue语句

continue语句用于跳过循环体中剩余的命令直接跳转到循环体的顶部,而重新开始循环的下一次重复。continue语句可以应用于for、while或until循环。continue语句的语法如下所示:

continue [n]

接下来看一个在循环中使用continue语句的实例:

#! /bin/bash

#如果运行脚本时未指定参数,则打印脚本的使用方法,并返回退出状态码1
[ $# -eq 0 ] && { echo "Usage: $O directory"; exit 1; }

#如果指定的目录不存在,则打印错误信息,并返回退出状态码1
[ ! -d $1 ] && { echo "Error: The directory $l does not exist."; exit 1;}

#如果没有成功切换到指定的目录,则打印相应的错误信息,并返回退出状态码1
cd $1 || { echo "Connot cd to the directory $1"; exit 1; }

#遍历指定目录下的所有文件
for filename in $(ls)
do

	#如果文件名不包含大写字母,则直接跳转到下一次循环
  if [ $filename != *[[:upper:]]* ]
  then
  
  #忽略for循环体中剩余的语句直接跳转到下一次循环
  continue
  
  fi

  #将变量filename中的字母转换为小写
  new=`echo $filename | tr 'A-Z' 'a-z'`
  
  #将文重命名
  mv $filename $new
  echo "The file $filename renamed to $new."

done

7.6小结

下面我们总结一下本章所学的主要知识:

  • Shell可以重复地执行特定的指令,直到特定的条件被满足时为止。这重复执行的一组命令就叫做循环。
  • 循环具有以下特点:
    • 循环条件中使用的变量必须是已初始化的,然后在循环中开始执行;
    • 在每一次循环开始时进行一次测试;
    • 重复地执行一个代码块。
  • 在for循环中,每次指定列表中的(iterm1…itermN)新值被赋给变量VAR后,for循环都会执行一次,它将重复运行‘do’和‘done’之间的所有语句,直到条件不满足时为止。
  • for循环也有三项表达式语法,其语法与C语言中常见的for循环使用方法相同。
  • while循环语句用于重复地执行一个命令列表。
  • while循环可以与read命令结合使用来读取一个文本文件。
  • while循环和专用命令“:”结合使用来定义一个无限循环。
  • 定义一个无限while循环可以使用以下三种命令: true命令、false命令和:命令
  • until循环与while循环类似,也同样基于一个条件。但until循环的判断条件正好与while循环的判断条件相反,until循环在条件为假的情况下才会持续地运行。一旦条件被满足,即为真,就会退出循环。
  • select循环语句具有如下特点:
    • select语句使用Bash内部变量PS3的值作为它的提示符信息。
    • 打印到屏幕上的列表LIST中的每一项会在前面加上一个数字编号。
    • 当用户输入的数字与某一个数字编号一致时,列表中相应的项即被赋予给变量VAR。
    • 如果用户输入的为空,将重新显示列表LIST中的项和提示符信息。
    • 可以通过添加一个退出选项,或输入CTRL+C或CTRL+D退出select循环。
  • break和continue是Bash中的循环控制命令,其用法与在其它编程语言中的同名语句完全一致。
  • break语句用于从for、while、until或select循环中退出,停止循环的执行。使用break n将退出n级嵌套循环。
  • continue语句用于跳过循环体中剩余的命令直接跳转到循环体的顶部,而重新开始循环的下一次重复。continue语句可以应用于for、while或until循环。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不是少爷.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值