SHELL编程笔记(二)之shell流程控制

时间:2021-10-10 15:07:40

Shell控制流程结构

  • 本章内容有:
       退出状态
       While、for和until loops循环
       If then else语句
       脚本中动作
       菜单
  • 条件控制语句
     If then else语句
    if语句测试条件,测试条件返回真(0)或假(1)后,可相应执行一系列语句。if语句结
    构对错误检查非常有用。其格式为:
if 条件1
then 命令1
elif 条件2
then 命令2
else 命令3
fi

让我们来具体讲解if语句的各部分功能。

 If 条件1 如果条件1为真
 Then 那么
 命令1 执行命令1
 elif 条件2 如果条件1不成立
 then 那么
 命令2 执行命令2
 else 如果条件1,2均不成立
 命令3 那么执行命令3
 fi 完成

if语句必须以单词fi终止。在if语句中漏写fi是最一般的错误。我自己有时也是这样。elif和else为可选项,如果语句中没有否则部分,那么就不需要elif和else部分。If语句可以有许多elif部分。最常用的if语句是if then fi结构。例题1:

#!/bin/sh
#author: li0924
if [  -lt  ];then
  echo "Yes, you are right"
fi

注意;then不要跟if一行;若是一行则需要添加;

例题二:通过测试设置为接受用户输入的变量可以测知用户是否输入信息。下面的例子中测试用户键入return键后变量name是否包含任何信息

#!/bin/sh
#author: li0924
echo -n "ENTRY YOUR NAME: "
read name
#"$name" = "" or -n $name
if [ -n $name ];then
echo "please input you name!"
fi

例题三:不必拘泥于变量或数值测试,也可以测知系统命令是否成功返回。对grep使用if语句找出grep是否成功返回信息

#!/bin/sh
#author: li0924
if grep -i "ready" * > /dev/null >&
then
echo "it is ready;here"
fi

例题四:环境变量用于测试条件,即LOGNAME是否包含root值。这类语句是加在脚本开头作为一安全性准则的普遍方法。当然LOGNAME可用于测试任何有效用

#!/bin/sh
#author: li0924
if [ $LOGNAME = "root" ];then
  echo "the LOGNAME is root"
else
  echo "NO"
fi
#!/bin/sh
#author: li0924
echo -n "please input your login name: "
read name
if [ -z $name ];then
 echo "please input your login name:"
 elif [ "$name" = "root" ];then
 echo "hello root";
 elif [ "$name" = "li0924" ];then
 echo "hello li0924";
 elif [ "$name" = "lottu" ];then
 echo "hello lottu";
fi

case语句

case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case语句格式如下:

case 值in
模式1)
命令1
. . .
;;
模式2)
命令2
. . .
;;
esac

case工作方式如上所示。取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至;;。取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号*捕获该值,再接受其他输入。
例题1:提示输入1到5,输入数字传入case语句,变量ANS设置为case取值测试变量ANS,ANS将与每一模式进行比较。如果匹配成功,则执行模式里面的命令直至;;,这里只反馈非用户数字选择的信息,然后case退出,因为匹配已找到

#!/bin/sh
#author: li0924
echo -n "please input 1-5: "
read ANS
case $ANS in
)
echo "you select 1"
;;
)
echo "you select 2"
;;
)
echo "you select 3"
;;
)
echo "you select 4"
;;
)
echo "you select 5"
;;
*)
echo "$0 :this is not between 1 and 5"
;;
esac

例题二:使用case时,也可以指定“|”符号作为或命令,例如vt100|vt102匹配模式vt100或vt102。下面的例子中,要求用户输入终端类型。如果输入为vt100或vt102,将匹配模式‘vt100|vt102’,执行命令是设置TERM变量为vt100。如果用户输入与模式不匹配,*用来捕获输入,其中命令为将TERM设置为vt100。最后在case语句外,导出TERM变量

#!/bin/sh
echo "choose vt100,vt102,vt200"
echo -n "please select one: "
read TERM
case $TERM in
vt100|vt102)
  TERM=vt100
  ;;
vt200)
  TERM=vt200 
  ;;
*)
  TERM="VT"
;;
esac
echo "$TERM"

例题三:case的一个有效用法是提示用户响应以决定是否继续进程。这里提示输入y以继续处理,n退出。如果用户输入Y,y或yes,处理继续执行case语句后面部分。如果用户输入N,n或no或其他响应,用户退出脚本

#!/bin/sh
#author: li094
echo "Do you wish next"
read I
case $I in
Y|y|yes)
  echo "OK"
  ;;
N|n|no)
  echo "NO"
  ;;
*)
  echo "unkown select"
  exit 
  ;;
esac
  • 循环控制语句

for循环控制语句

for循环一般格式为:

for varname in list
do
command 
command 
...
done

当变量值在列表里,for循环即执行一次所有命令,使用变量名访问列表中取值。命令可为任何有效的shell命令和语句。变量名为任何单词。In列表用法是可选的,如果不用它,for循环使用命令行的位置参数。
in列表可以包含替换、字符串和文件名,下面看一些例子
例题一:此例仅显示列表1 2 3 4 5,用变量名访问列表:

#!/bin/sh
#author: li0924
for i in     
do
 echo $i
done

例题二:对for循环使用ls命令;这个循环执行ls命令,打印当前目录下所有文件

#!/bin/sh
#author: li0924
for i in `ls`
do 
 echo $i
done

例题三:In列表用法是可选的,如果不用它,for循环使用命令行的位置参数

#!/bin/sh
#author: li0924
for i        
do
 echo "this is $i paramter"
done

例题四:用for循环备份所有文件,只需将变量作为cp命令的目标参数。这里有一变量.bak,当在循环中使用cp命令时,它作为此命令目标文件名。列表命令为ls。只针对普通文件;非文件夹

#!/bin/sh
#author: li0924
for i in `ls -l | awk '{if(substr($1,1,1)=="-") print $NF}'`
do
 if cp $i $i.bak 
 then
   exit 
 else
   exit   
 fi
done

for循环嵌入
嵌入循环可以将一个for循环嵌在另一个for循环内

for varname1 in list1
do
for varname2 in list2
do
command 
. . .
done
done

while循环
while循环用于不断执行一系列命令,也用于从输入文件中读取数据,其格式为:

while command
do
command 
command 
...
done

虽然通常只使用一个命令,但在while和do之间可以放几个命令。命令通常用作测试条件。只有当命令的退出状态为0时,do和done之间命令才被执行,如果退出状态不是0,则循
环终止。命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假

题目一:以下是一个基本的while循环,测试条件是:如果COUNTER小于5,那么条件返回真。COUNTER从0开始,每次循环处理时, COUNTER加1

#!/bin/sh
#author: li0924
counter=
while [ $counter -lt  ]
do
echo "$counter"
counter=`expr $counter + `
done

题目二:while循环最常用于从一个文件中读取数据,因此编写脚本可以处理这样的信息。假定要从下面包含雇员名字、从属部门及其ID号的一个文件中读取信息文件worker.txt

Louise Conrad:Accounts:ACC8987
Peter Jamas:Payroll:PR489
Fred Terms:Customer:CUS012
James Lenod:Accounts:ACC887
Frank Pavely:Payroll:PR489
#!/bin/sh
#author: li0924
while read list
do 
 echo $list;
done < worker.txt

例题三:输出时要去除冒号域分隔符,可使用变量IFS。在改变它之前保存IFS的当前设置。然后在脚本执行完后恢复此设置。使用IFS可以将域分隔符改为冒号而不是空格或tab键

#!/bin/sh
#author: li0924
#SAVEIFS=$IFS
IFS=:
while read name dept id
 do
  echo -e "$name\t$dept\t$id"
 done < worker.txt
#IFS=$SAVEIFS

注意:只要理解上面脚本的意思就行了;完全可以用awk来代替!

总结:以上代码都很简单;容易理解学习!都经过测试!