您的位置:首页 > 运维架构 > Shell

Shell脚本之条件选择与循环

2017-08-27 17:18 246 查看

前言

Bash语言是过程式编程语言,这篇文章主要讲到:条件选择、循环,这两种用法。

条件选择语句主要用到的有if,case这两种判断语句。

Shell中有3种循环,分别是for,while,until,until与while正好相反,前者条件为假则执行,后者条件为真时执行。

条件选择

if条件判断

单分支条件判断:

if 判断条件;then
条件为真的分支代码
fi


双分支条件判断:

if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi


多分支条件判断:

if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi


注:逐条件进行判断,第一次遇为“真”条件时,执行其分支, 而后结束整个if语句

下面用if条件判断语句写一个脚本来深入的理解:

#!/bin/bash
#
if ping -c1 -W2 station1 &> /dev/null; then
echo 'Station1 is UP'
elif grep "station1" ~/maintenance.txt &> /dev/null
then
echo 'Station1 is undergoing maintenance'
else
echo 'Station1 is unexpectedly DOWN!'
exit 1
fi


注:这个脚本,第一步是先判断station1是否能ping通,如果ping通了就在屏幕上打印Station1是UP状态。判断结束。

如果不能ping通就跳到下一个判断,查询~/maintenance.txt里面有没有station1,如果能查询到,则在屏幕上打印

station1 是在维护状态,半段结束。如果依然不能在在~/maintenance.txt里面查询到station1,则跳到下一步,以上

的判断都不为真,则打印station1是DOWN状态,并退出返回状态数1.

case语句

case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac


注:

case支持glob风格的通配符:

*: 任意长度任意字符

?: 任意单个字符

[]:指定范围内的任意单个字符

a|b: a或b

国际惯例,来个脚本加深理解:

#!/bin/bash
read -p 'Can I ask you out to play?(yes|no)'  go
case    $go    in
[yY]|[yY][eE][sS])
echo "Let's go."
;;
[nN]|[nN][oO])
echo "That's too bad"
;;
*)
echo "Are you turning me down?"
;;
esac
unset go


注:case语句支持glob风格的通配符,用read来交互式输入变量$go,询问我能约你出去玩吗?这时用户输入的字符

将会被赋值到变量$go上面,如果变量go的值等于y或是Y或是yes(各种不同大小写皆可),就会打印let’s go.然后

结束,亦或是变量go的值等于n或是N或是no(各种大小写皆可),就会打印That’s too bad,然后结束。如果变

量go的值不等于上面的任何一个,就打印Are you turning me down?然后结束。

循环

基本结构

循环执行
将某代码段重复运行多次
重复运行多少次:
循环次数事先已知
循环次数事先未知
有进入条件和退出条件


for循环

普通for循环

for 变量名 in 列表;do
循环体
done


嵌套for循环

for 变量名1 in 列表1;do
循环体1
for 变量名2 in 列表2;do
循环体2
done
done


执行机制:

依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体;

直到列表中的元素耗尽,循环结束

列表生成方式:

(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用;
\$@, \$*


国际惯例,来个脚本。

用*打印一个等腰三角形,带闪烁带随机颜色的哦。

if [ $# = 0 ];then
read -p "你想打印几行的等腰三角形:" s
else
s=$1
fi
if [ "$s" -gt 0  ] &> /dev/null;then
for n in `seq  $s`
do
i=$[$s-$n]
m=$[2*$n-1]
for i in `seq  $i`; do
echo -n  " "
done
for m in `seq  $m`; do
color=$[$RANDOM%6+1]
let textcolor=$color+30
echo -en "\033[1;`echo $textcolor`;5m*\033[0;25m"
if [ $s -gt 10 ];then
sleep 0.01
else
sleep 0.05
fi
done
echo
done
else
echo "please...给个大于零的整数吧"
fi


注:第一步,先判断这个脚本后面是否跟了参数,如果没有,就输出 你想打印几行的等腰三角形:提示用户输入数字,

然后赋值给s(我这里为了偷懒只写了一个字母,生产中变量一定不要只写一个字母,很容易出错。),亦或是脚本后面

已经跟了参数也赋值给s,接下来判断变量s是不是大于0的整数,如果不是就输出please…给个大于零的整数吧,然后

退出。如果是大于0的整数,就进入第一个for循环,n指的是打印的第几行,i指得是这一行要打印的空白字符数,m指

的是这一行要打印的*的数量。嵌套第一个for循环,打印这一行要打印的空白字符数i个,嵌套第二个for循环,打印这

一行要打印的*的数量,里面做了随机颜色,和闪烁的特效,并用if判断语句,当行数s大于10时就以更快的速度打印。

while循环

while CONDITION; do
循环体
done


CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环

因此:CONDTION一般应该有循环控制变量;而此变量的值 会在循环体不断地被修正

进入条件:CONDITION为true

退出条件:CONDITION为false

while循环的特殊用法(遍历文件的每一行):

while read line; do
循环体
done < /PATH/FROM/SOMEFILE


依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将 行赋值给变量line

until循环

until循环与while循环恰恰相反,进入条件为假,为真时就结束了。

until CONDITION; do
循环体
done


进入条件: CONDITION 为false

退出条件: CONDITION 为true

循环控制语句

continue

用于循环体中

continue
:提前结束第N层的本轮循环,而直接进入下一 轮判断;

最内层为第1层

while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done


break

用于循环体中

break
:提前结束第N层循环,最内层为第1层

while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done


shift

循环控制shift命令

shift

用于将参量列表 list 左移指定次数,缺省为左移一次。

参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift

./doit.sh a b c d e f g h

./shfit.sh a b c d e f g h

脚本详解:

while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done


注:当输入的参数大于0时不停的循环下去,比如输入的参数是aa bb cc ,那么第一次打印的就是

aa bb cc,经过shift去掉第一个参数,再次循环,打印bb cc,再经过shift,再去掉一个参数,循环,

打印cc,再经过shift去掉一个参数,此时以没有参数了,循环判断不大于0了,循环结束。

select循环与菜单

select variable in list
do
循环体命令
done


select 循环主要用于创建菜单,按数字顺序排列的 菜单项将显示在标准错误上,并显示 PS3 提示符, 等待用户输入

用户输入菜单列表中的某个数字,执行相应的命令

用户输入被保存在内置变量 REPLY 中

select与case

select 是个无限循环,因此要记住用 break 命令退 出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环

select 经常和 case 联合使用

与 for 循环类似,可以省略 in list,此时使用位置参量

这里放上一个我用select与case写的脚本:

PS3="please choose you menu: "
select menu in exit huimian lamian hulatang yangroutang
do
case $menu in
huimian)
echo ¥10
;;
lamian)
echo ¥15
;;
hulatang)
echo ¥5
;;
yangroutang)
echo ¥20
;;
exit)
echo "真的不来一点?"
break
;;
*)
echo "没有这个菜..."
esac
echo you choose is $menu
echo you input is $REPLY
done


ღ ღ ღ 如果觉得文章对您有用,不妨赞一下ღ ღ ღ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息