shell脚本编写 之 条件选择,条件判断,循环语句

1 概述

编写shell脚本,一般离不开条件选择,条件判断以及循环语句。掌握这三个语法,将大大提高脚本的编写效率,使得脚本编写更加灵活,完成X相对复杂的工作

2 条件选择if语句

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

if是根据判读条件的命令的退出状态来执行命令,if语句可嵌套

单分支

if 判断条件;then

条件为真的分支代码

fi

双分支

if 判断条件; then

条件为真的分支代码

else

条件为假的分支代码

fi

多分支

if 判断条件1; then

条件为真的分支代码

elif 判断条件2; then

条件为真的分支代码

elif 判断条件3; then

条件为真的分支代码

else

以上条件都为假的分支代码

fi

例子

比较数字大小结果真假判断

read -p "Please input nu: " nu

[[ $nu =~ ^[0-9]+$ ]] || { echo "Your input is not num";exit 8; }

if [ "$nu" -gt 90 ];then

echo "$nu is bigger than 90"

elif [ "$nu" -lt 50 ];then

echo "$nu is less than 50"

else

echo "Your input $nu is between range 50-90"

fi

执行命令结果真假判断

read -p "please input ip: " ip

if  ping -c 1 -W 1 $ip &>/dev/null; then

echo "$ip is up"

elif grep "$ip" /root/list &>/dev/null

then

echo  "host "$ip" is under maitenance"

else  echo "$ip is unexpectedly down,please check"

fi

3 条件判断:case语句

语法如下

case 变量引用($var,注意有$符号引用)  in

PAT1)

分支1

;;

PAT2)

分支2

;;

......

*)

默认分支

;;

esac

这里的分支x可以是命令的组合,不是单纯的一条命令

case支持glob风格的通配符:

*: 任意长度任意字符

?: 任意单个字符

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

a|b: a或b,当匹配到不同的字符,但是要执行相同的分支命令是,可以用这个命令简化判断

例子

#!/bin/bash

read -p "Please input your choice: " choice

final=`echo "$choice" |tr [[:upper:]] [[:lower:]]`

case $final in

y|yes)

echo "You input "$choice",and your choice is yes"

;;

n|no)

echo "You input "$choice",and your choice is no";

;;

y???es)

echo "You input $choice,it has three character between yes"

;;

[sunny])

echo "You input $choice,it only has one character"

;;

*)

echo "Your choice is $choice,it is not the answer"

;;

esac

截图如下

4 循环语句

将某代码段重复运行多次,以下三个关键字for, while, until各自的语法构成不同的循环语句

其中

for默认将列表的值依次执行完成后退出

while和until有进入条件和退出条件

重复运行的次数有两类

a.循环次数事先已知

b.循环次数事先未知

4.1 for 循环

4.1.1 for 常规的列表循环

语法如下:

for 变量名 (如 var,不需要加$引用变量值) in 列表;do

循环体(命令组合)

done

for循环执行机制:

依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束

for循环 列表 生成方式:

(1) 直接给出列表

(2) 整数列表:

(a) {start..end}

(b) $(seq[start [step]] end)

(3) 返回列表的命令:$(COMMAND) 可以表达为`COMMAND`,反向单引号引起来

(4) 使用glob,如:*.sh

(5) 变量引用;$@, $*

4.1.2 例子:

4.1.2.1 直接给出列表型

i=1

for var in a b c d

do

echo "$i cycle the var is $var"

let i++

done

4.1.2.2 整数列表:{start..end..step}型

如果不指定步进值(step),那么默认是步进1

i=1

for var in {3..15..2}

do

echo "$i cycle the var is $var"

let i++

done

4.1.2.3 整数列表:$(seq[start [step]] end) 型

#如果是 seq end  从1开始递增到end,每次增加1

#如果是 seq start end  从start开始递增到end,每次递增1

#如果是 seq[start] [step] [end] 从start开始,每次递增step,直到end

i=1

for var in $(seq 3 2 9)

do

echo "$i cycle the var is $var"

let i++

done

4.1.2.4 返回列表的命令 $(COMMAND)型

for var in $(ls /root/)

do

echo  "$i file is "$var", type is `file /root/$var`"

let i++

done

echo

4.1.2.5 使用glob,如:*.sh或/root/* 型

for var in /root/*

do

echo  "$i file is "$var", type is `file $var`"

let i++

done

echo

4.1.2.6 变量引用;$@, $*型

for var in $@

do

echo  "$i cycle,and now para is $1,var is $var,\$@ is $@"

let i++

shift

done

echo

4.1.3  for循环的特殊格式:

语法如下

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))

do

循环体

done

控制变量初始化:仅在运行到循环代码段时执行一次

控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

双小括号方法,即((…))格式,也可以用于算术运算

双小括号方法也可以使bash Shell实现C语言风格的变量操作,如((I++))

该for循环的执行过程如下

进入循环的时候,先不判断真假,直接执行 控制变量初始化

然后执行  条件判断表达式 ,会判断真假 ,条件为真,开始进入循环

执行循环

执行完循环后

执行  控制变量的修正表达式

然后条件判断表达式

执行  控制变量的修正表达式

然后条件判断表达式,

。。。。。。。

直到不满足条件判断表达式这个条件后退出循环

逻辑图如下

例子

read -p "Please input your nu to cal 1+2+...+nu: " nu

s=0

for ((i=1;i<=$nu;i=i+1))

do

s=$(($s+$i))

echo "it is the $i cycle."

done

echo "1+2...+$nu=$s"

以上脚本通过调试 bash -x 结果截图如下

4.2 while循环

4.2.1 语法

while CONDITION(条件判断); do

循环体

done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;

条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环

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

进入条件:CONDITION为true

退出条件:CONDITION为false

4.2.2 while循环的特殊用法:

4.2.2.1 读入文件

while read line; do  //注意,这里的line只是变量,可以自己命名

循环体

done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE这个文件中的每一行,且将行赋值给变量line,每次读入一行进入循环,进行相应的处理

4.2.2.2 将结果传入while

将命令的结果传给while,用管道来传,每次读入命令结果得到一行

命令 | while read 变量; do

循环体

其中管道命令只能处理标准输出,所以要确保命令有标准输出

done

4.2.2.3 创建无限循环

while true; do

循环体

done

4.2.3例子

4.2.3.1 普通循环 九九乘法表

i=1

while [ "$i" -lt 10 ];do

for (( j=1;j<="$i";j++)) do

echo -e -n "$i*$j=$[ $i*$j ]\t"

done

echo

let i++

done

4.2.3.2 读入文档内容

while 每一次会把输入的文档/root/tt的每一行输入进行处理,等这行完成处理后,

再输入文档的下一行,直到所有的循环都结束

i=1

while read line;do

echo "$i cycle is \$line is <$line>"

let i++

echo "$line" | grep gt

echo "$line" | sed -nr 's/useage=.*/for test sed/p'

echo

done

4.2.3.3 管道输入

以下命令将 df|grep /dev/sd 的结果通过管道一行一行传入给到变量line。然后进入循环做处理

df|grep /dev/sd  | while read line;do

dev=`echo "$line"| cut -d " " -f1`

use=`echo "$line"| sed -r 's/.* ([0-9]+)%.*/\1/'`

if [ "$use" -gt 3 ];then

echo "Warning "$dev"'s usage is over 3%,it is $use,please check"

else

echo ""$dev"'s usage is safe,it is $use"

fi

done

4.2.3.4 创建循环体

每个两秒打印hello

while true;do

echo hello

sleep 2

done

4.3 until

4.3.1 语法

until CONDITION; do

循环体

done

进入条件:CONDITION 为false

退出条件:CONDITION 为true

until就是和while相反,一般可以用until实现的循环,都可以用while来实现,所以until可以了解一下即可。

创建无限循环

until false; do

循环体

Done

4.3.2 例子

4.3.2.1 until普通循环

当i大于6的时候进入循环,小于或者等于6的时候退出循环

i=10

until [ $i -le 6 ];do

echo \$i is $i,bigger than 6

let i--

echo "after i--,now i is $i"

echo

done

4.3.2.2 无效循环的脚本

打印it is false,然后睡2秒

until false ;do

echo "it is false"

sleep 2

done

5 小结

使用什么语法进行循环,或者是条件选择或者条件判断,都要根据具体情况来定,同时也是根据个人写脚本的习惯而定,比如有些人就喜欢用while来写循环语句,但是有一个原则就是,尽量把算法定好,防止多次的循环,占用大量的资源,对系统造成负担。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容