bash中的循环命令用法原理(for, while, until, select)

循环命令

循环命令就是反复执行一个命令或者一组命令,直到完成事先设置好的次数或者达到某种条件。bash
shell有三种循环:for循环,while循环和until循环。
for命令
for循环命令用于根据项目清单确定的次数执行命令。例如,你可以根据文件或者用户清单执行相同的命令。for命令后面紧跟着用户自定义变量-关键字in,然后是一个单词清单。第一次执行循环,单词列表中的第一个单词被赋值给变量。一旦单词被赋值给赋值变量,就进入循环体,执行关键字
do和done之间的命令。下一次的循环,第二个单词被赋值给变量,如此继续。循环体由do开始到done结束。当清单中的所有单词都轮换过一次以后,循环结束,程序控制继续done后面的语句。

格式

for  variable in world_list
do
  commands
done

#如果需要将for循环写成一行,则单词列表和do之间需要用分号来分隔.
for variable in world_list; do commands; done  

示例一

#!/usr/bin/bash
for name in Tom Dick Harry Joe
do 
   echo "Hi, $name"
done   
echo "Out of loop."

示例二

#!/usr/bin/bash
for person in $(cat my file)
do 
   mail $person < letter
   echo "$person was sent a letter."
done
   
echo "The letter has been sent."

示例三

#!/usr/bin/bash
dir=/home/tony/backupscripts
for file in backup{1..5} 
do
  if [ -f $file ] # 检查当前目录下该文件是否真实存在
  then
      cp "$file" $dir/$file.bak
      echo "The $file is backuped in $dir"
  fi
done      

单词列表中的 @ @和 *变量。在不使用双引号的时候是一样的。当使用引号的时候, *的值是一个字符串,而 @的值是一组分开的单词。

#!/usr/bin/bash
# scriptname: greet
for name in $*
do 
  echo "Hi $name"
done  
(The Command Line)
$ greet Tom Jerry Larry Wall
# Tom
# Jerry
# Larry
# Wall

示例四

#!/bin/bash
#scriptname: perm_check
for filename
do
  if [[ -f $filename && ! -x $filename ]] 
  then
     chmod +x $filename
     echo "$filename now has exectue permission."
  fi
done
(The Command Line)     
$ perm_check * # 通配符会扩展成当前目录下面的所有文件
# file1 now has exectue permission.
# file2 now has exectue permission.

while命令

while命令判断它后面的命令,如果退出状态值是0,就执行循环体内的命令,直到done,控制返回循环体的顶部,while命令将再次检验命令的退出状态,直到退出状态为非0,程序继续执行done后面的语句。

格式

while command
do
  commands
done  

示例一

#!/usr/bin/bash
num=0
while (( $num < 10 ))
do
  echo -n "$num"
  (( num = $num + 1 )) # or let num+=1 or (( num += 1 ))
done

示例二

#!/usr/bin/bash
# scriptname: quiz
echo "Who was the 2nd U.S president to be impeached?"
read answer
while [[ "$answer" != "Bill Clinton" ]]
do
  echo "wrong try again"
  read answer
done
echo "You got it"

示例三

#!/usr/bin/bash
# script: sayit
echo "Type q to quit."
go=start
while [ -n "$go" ]
do  
  echo -n I love you
  read word
  if [[ $word = [Qq] ]]
  then
     echo "I will always love you!"
     go= # or break
  fi  
done     

until命令
until命令的用法跟while命令的用法类似,只是在until后面的语句为假的时候执行循环体,例如一个命令的退出状态值返回为非0。当到达done关键字以后就自动返回循环体的顶部,until命令再次检验命令的退出状态值。循环一直继续,直到until后面的退出状态值为0。当退出状态值为0时,循环退出,程序从done后面继续。

until command
do
  commands
done

示例一

#!/usr/bin/bash
until who | grep Yang
do
  sleep 5
done
# 除非Yang登录了终端,否则程序每隔5秒循环一次  

示例二

#!/usr/bin/bash

let hour=0
until (( $hour > 24 )) # or [ $hour -gt 24 ]
do
   case "$hour" in
   [0-9]|1[0-1]) 
        echo "Good morning!"
        ;;
   12)
        echo "Lunch time!"
        ;;
   1[3-7])
        echo "Siesta time!"
        ;;
   *)
        echo "Good night!"
        ;;
   esac
   
   let hour+=1
done   

select命令和菜单
here文档是建立菜单的简单方法,但是bash介绍了另外一种循环机制,叫做select循环,主要的作用就是建立菜单。一个数字化的菜单显示在标准错误上,PS3用来提示用户输入。默认的PS3是#?。在PS3提示显示以后,shell就等待用户输入。输入的是该菜单中的数字,若输入被保存在指定变量REPLY中,则变量REPLY中的数字与括号右边选项清单中的字符串有着对应关系。
case命令与select命令连用,允许用户在菜单中选择,基于选择执行相应的命令。LINES和COLUMNS变量可以用来决定在终端显示的菜单的层。输出显示在标准错误上,每一个选项前都有数字和右括号,PS3提示显示在菜单的底部。因为select命令是一个循环命令,因此一定要记得用break命令退出循环或者exit命令退出脚本。

格式
select var in wordlist
do
  commands
done  

示例一

#!/usr/bin/bash
PS3="Select a program to exectue: "
select program in 'ls -F' pwd date
do
  $program
done
  
(The Command Line)
Select a program to exectue: 2
1) ls -F
2) pwd
3) date
# /home/yang
# 在执行脚本的时候,PS3里面的字符串会显示在菜单的底部

示例二

#!/usr/bin/bash
PS3="Please choose one of the three boys: "
select name in tom jerry matz
do
   case $name in
   tom)
      echo "Tom is a cool dude!"
      break
      ;;
   jerry|matz)
      echo "Jerry and matz are both wonderful"
      break
      ;;
   *)
     echo "$REPLY is not one of your choice" 1>&2 
     echo "Try again"
     ;;
   esac       
done

示例三

#!/usr/bin/bash
PS3="Please enter the Tom's age: "
select choice in 20 30 40
do
  case $REPLY in
  1) 
    echo "you choose the right age ${choice}!"
    break;;
  2)
    echo "you choose the wrong age ${choice}!"
    break;;
  3)
    echo "you choose the wrong age ${choice}!"
    break;;
  *)
    echo -e "$REPLY is not a valid choice, try again!\n"
    REPLAY= # cause the menu to be redisplayed
  esac
done        


looping命令

在某些情况下,需要中断循环并回到循环顶部,或者需要一种方法结束当前循环,bash提供了一个命令来处理这些情况。
shift命令。shift命令用来把参量列表位移指定次数。没有参数的shift把参数变量向左位移一位。一旦位移发生,被位移出列表的参数就被永远删除了。通常在while循环中,shift用来读取列表中的参量。

$ set $(date)
$ echo $# # 5
$ shift
$ echo $# #参量往左移动一位,此时参量个数减1,变为4
$ shift 2
$ echo $# #参量往左移动两位,此时参量个数继续减2,变为2
$ shift 5
# 如果尝试位移多于参量总数的次数,shell会打印错误消息.

#!/usr/bin/bash
set $(date)
while (( $# > 0 ))
do
  echo -n "$# "
  shift
done
# 6 5 4 3 2 1

内建break命令
内建break命令用来从循环中抢先退出,但是不退出程序。执行break以后,控制从关键字done开始执行。break命令可以从内层循环中退出,所以如果你使用循环嵌套的话,break可以用一个数字作为参数,运行你指定break强行退出的循环的层数。如果你有三层嵌套循环,最外面的循环数是1,中间层的循环是2,最里面的循环数为3。在退出无限循环的时候,break非常有用。

格式
break[n]

示例一

#!/usr/bin/bash
while true; do
    echo Are you ready to move on\?
    read answer
    if [[ "$answer" == [Yy] ]]
    then
        break
     else
        echo "Try again"
     fi
done
echo "Here we are"           

continue命令
如果某些条件为真,continue命令控制跳转到循环顶部。所有continue命令后面的语句都将被忽略。如果嵌套循环,continue命令就跳转到最内的循环的顶部。如果一个数字作为它的参数,控制就可以在指定的任何层的循环的顶部重新开始执行。如果你有三层循环嵌套,最外面的循环号是3,中间层的循环号是2,最内的循环号是1。

#!/usr/bin/bash
for name in $(cat mail_list)
do 
  if [[ "$name" == ricard ]];then
     continue
  else
     mail $name < memo
  fi      
done

# continue后面的数字如果大于循环的嵌套层数,则会退出循环

嵌套循环和循环控制
当你使用嵌套循环的时候,continue命令和break命令都被赋予一个整数作为参数,控制流到第几层循环。

#!/usr/bin/bash
for month in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
do
  for week in 1 2 3 4
  do 
    echo -n "Processing the month of $month. ok?"
    read answer
    if [[ "$answer" == n || -z "$answer" ]]
    then
       continue 2
    else
       echo -n  "process week $week of $month ?"
       read answer
       if [[ "$answer" = n || -z $answer ]]
       then
           continue
       else    
          echo "Now processing week $week of $month."
          sleep 1 
          echo "Done processing..."
       fi      
    fi
  done
done    
       

发布了9 篇原创文章 · 获赞 3 · 访问量 151

猜你喜欢

转载自blog.csdn.net/tonyyong90/article/details/105603249