学校网站源码免费,做网站软件j,天津智能网站建设哪家好,网站建设中英文版【BASH】回顾与知识点梳理 十九 十九. 循环 (loop)19.1 while do done, until do done (不定循环)19.2 for...do...done (固定循环)19.3 for...do...done 的数值处理(C写法)19.4 搭配随机数与数组的实验19.5 shell script 的追踪与 debug19.6 what_to_eat-2.sh debug结果解析 该… 【BASH】回顾与知识点梳理 十九 十九. 循环 (loop)19.1 while do done, until do done (不定循环)19.2 for...do...done (固定循环)19.3 for...do...done 的数值处理(C写法)19.4 搭配随机数与数组的实验19.5 shell script 的追踪与 debug19.6 what_to_eat-2.sh debug结果解析 该系列目录 -- 【BASH】回顾与知识点梳理目录
十九. 循环 (loop)
除了 if…then…fi 这种条件判断式之外循环可能是程序当中最重要的一环了 循环可以不断的执行某个程序段落直到用户设定的条件达成为止。 所以重点是那个『条件的达成』是什么。除了这种依据判断式达成与否的不定循环之外 还有另外一种已经固定要跑多少次的循环形态可称为固定循环的形态呢底下我们就来谈一谈
19.1 while do done, until do done (不定循环)
一般来说不定循环最常见的就是底下这两种状态了
while [ condition ] 中括号内的状态就是判断式
do do 是循环的开始程序段落
done done 是循环的结束while 的中文是『当…时』所以这种方式说的是『当 condition 条件成立时就进行循环直到condition 的条件不成立才停止』的意思。还有另外一种不定循环的方式
until [ condition ]
do程序段落
done这种方式恰恰与 while 相反它说的是『当 condition 条件成立时就终止循环 否则就持续进行循环的程序段。』是否刚好相反啊我们以 while 来做个简单的练习好了。 假设我要让使用者输入yes 或者是 YES 才结束程序的执行否则就一直进行告知用户输入字符串。
[dmtsaistudy bin]$ vim yes_to_stop.sh
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
while [ ${yn} ! yes -a ${yn} ! YES ]
doread -p Please input yes/YES to stop this program: yn
done
echo OK! you input the correct answer.上面这个例题的说明是『当 ${yn} 这个变数不是 “yes” 且 ${yn} 也不是 “YES” 时才进行循环内的程序。』 而如果 ${yn} 是 “yes” 或 “YES” 时就会离开循环啰那如果使用 until 呢呵呵有趣啰 他的条件会变成这样
[dmtsaistudy bin]$ vim yes_to_stop-2.sh
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
until [ ${yn} yes -o ${yn} YES ]
doread -p Please input yes/YES to stop this program: yn
done
echo OK! you input the correct answer.仔细比对一下这两个东西有啥不同喔 ^_^再来如果我想要计算 123…100 这个数据呢 利用循环啊他是这样的
[dmtsaistudy bin]$ vim cal_1_100.sh
#!/bin/bash
# Program:
# Use loop to calculate 123...100 result.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
s0 # 这是加总的数值变数
i0 # 这是累计的数值亦即是 1, 2, 3....
while [ ${i} ! 100 ]
do
i$(($i1)) # 每次 i 都会增加 1
s$(($s$i)) # 每次都会加总一次
done
echo The result of 123...100 is $s嘿嘿当你执行了『 sh cal_1_100.sh 』之后就可以得到 5050 这个数据才对啊这样瞭呼 那么让你自行做一下如果想要让用户自行输入一个数字让程序由 12… 直到你输入的数字为止 该如何撰写呢应该很简单吧答案可以参考一下习题练习里面的一题喔
19.2 for…do…done (固定循环)
相对于 while, until 的循环方式是必须要『符合某个条件』的状态 for 这种语法则是『 已经知道要进行几次循环』的状态他的语法是
for var in con1 con2 con3 ...
do程序段
done以上面的例子来说这个 $var 的变量内容在循环工作时
第一次循环时 $var 的内容为 con1 第二次循环时 $var 的内容为 con2 第三次循环时 $var 的内容为 con3 …
我们可以做个简单的练习。假设我有三种动物分别是 dog, cat, elephant 三种 我想每一行都输出这样『There are dogs…』之类的字样则可以
[dmtsaistudy bin]$ vim show_animal.sh
#!/bin/bash
# Program:
# Using for .... loop to print 3 animals
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
for animal in dog cat elephant
doecho There are ${animal}s....
done等你执行之后就能够发现这个程序运作的情况啦让我们想象另外一种状况由于系统上面的各种账号都是写在 /etc/passwd 内的第一个字段你能不能透过管线命令的 cut 捉出单纯的账号名称后以 id 分别检查使用者的标识符与特殊参数呢由于不同的 Linux 系统上面的账号都不一样此时实际去捉 /etc/passwd 并使用循环处理就是一个可行的方案了程序可以如下
[dmtsaistudy bin]$ vim userid.sh
#!/bin/bash
# Program
# Use id, finger command to check system accounts information.
# History
# 2015/07/17 VBird first release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users$(cut -d : -f1 /etc/passwd) # 撷取账号名称
for username in ${users} # 开始循环进行
doid ${username}
donecat /etc/passwd|cut -d: -f 1|xargs -n 1 id 执行上面的脚本后你的系统账号就会被捉出来检查啦这个动作还可以用在每个账号的删除、重整上面呢 换个角度来看如果我现在需要一连串的数字来进行循环呢举例来说我想要利用 ping 这个可以判断网络状态的指令 来进行网络状态的实际侦测时我想要侦测的网域是本机所在的192.168.1.1~192.168.1.100由于有 100 台主机 总不会要我在 for 后面输入 1 到 100 吧此时你可以这样做喔
[dmtsaistudy bin]$ vim pingip.sh
#!/bin/bash
# Program
# Use ping command to check the networks PC state.
# History
# 2015/07/17 VBird first release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
network192.168.1 # 先定义一个网域的前面部分
for sitenu in $(seq 1 100) # seq 为 sequence(连续) 的缩写之意
do
# 底下的程序在取得 ping 的回传值是正确的还是失败的ping -c 1 -w 1 ${network}.${sitenu} /dev/null result0 || result1
# 开始显示结果是正确的启动 (UP) 还是错误的没有连通 (DOWN)if [ ${result} 0 ]; thenecho Server ${network}.${sitenu} is UP.elseecho Server ${network}.${sitenu} is DOWN.fi
done上面这一串指令执行之后就可以显示出 192.168.1.1~192.168.1.100 共 100 部主机目前是否能与你的机器连通 如果你的网域与鸟哥所在的位置不同则直接修改上头那个 network 的变量内容即可其实这个范例的重点在 $(seq ..) 那个位置那个 seq 是连续 (sequence) 的缩写之意代表后面接的两个数值是一直连续的 如此一来就能够轻松的将连续数字带入程序中啰 除了使用 $(seq 1 100) 之外你也可以直接使用 bash 的内建机制来处理喔可以使用{1..100} 来取代 $(seq 1 100) 那个大括号内的前面/后面用两个字符中间以两个小数点来代表连续出现的意思例如要持续输出 a, b, c…g 的话 就可以使用『 echo {a…g} 』这样的表示方式 最后让我们来玩判断式加上循环的功能我想要让用户输入某个目录文件名 然后我找出某目录内的文件名的权限该如何是好呵呵可以这样做啦
[dmtsaistudy bin]$ vim dir_perm.sh
#!/bin/bash
# Program:
# User input dir name, I find the permission of files.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1. 先看看这个目录是否存在啊
read -p Please input a directory: dir
if [ ${dir} -o ! -d ${dir} ]; then
echo The ${dir} is NOT exist in your system.
exit 1
fi
# 2. 开始测试文件啰
filelist$(ls ${dir}) # 列出所有在该目录下的文件名
for filename in ${filelist}
do
perm
test -r ${dir}/${filename} perm${perm} readable
test -w ${dir}/${filename} perm${perm} writable
test -x ${dir}/${filename} perm${perm} executable
echo The file ${dir}/${filename}s permission is ${perm}
done呵呵很有趣的例子吧利用这种方式你可以很轻易的来处理一些文件的特性呢。接下来让我们来玩玩另一种 for 循环的功能吧主要用在数值方面的处理喔
19.3 for…do…done 的数值处理(C写法)
除了上述的方法之外for 循环还有另外一种写法语法如下
for (( 初始值; 限制值; 执行步阶 ))
do程序段
done这种语法适合于数值方式的运算当中在 for 后面的括号内的三串内容意义为
初始值某个变量在循环当中的起始值直接以类似 i1 设定好限制值当变量的值在这个限制值的范围内就继续进行循环。例如 i100执行步阶每作一次循环时变量的变化量。例如 ii1。
值得注意的是在『执行步阶』的设定上如果每次增加 1 则可以使用类似『i』的方式亦即是 i 每次循环都会增加一的意思。好我们以这种方式来进行 1 累加到使用者输入的循环吧
[dmtsaistudy bin]$ vim cal_1_100-2.sh
#!/bin/bash
# Program:
# Try do calculate 12....${your_input}
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p Please input a number, I will count for 12...your_input: nu
s0
for (( i1; i${nu}; ii1 ))
dos$((${s}${i}))
done
echo The result of 123...${nu} is ${s}一样也是很简单吧利用这个 for 则可以直接限制循环要进行几次呢
19.4 搭配随机数与数组的实验
现在你大概已经能够掌握 shell script 了好了让我们来做个小实验假设你们公司的团队中经常为了今天中午要吃啥搞到头很昏 每次都用猜拳的好烦喔有没有办法写支脚本用脚本搭配随机数来告诉我们今天中午吃啥好呵呵执行这只脚本后 直接跟你说要吃啥那比猜拳好多了吧哈哈
要达成这个任务首先你得要将全部的店家输入到一组数组当中再透过随机数的处理去取得可能的数值再将搭配到该数值的店家秀出来即可 其实也很简单让我们来实验看看
[dmtsaistudy bin]$ vim what_to_eat.sh
#!/bin/bash
# Program:
# Try do tell you what you may eat.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATHeat[1]卖当当汉堡 # 写下你所收集到的店家
eat[2]肯爷爷炸鸡
eat[3]彩虹日式便当
eat[4]越油越好吃大雅
eat[5]想不出吃啥学餐
eat[6]太师父便当
eat[7]池上便当
eat[8]怀念火车便当
eat[9]一起吃泡面
eatnum9 # 需要输入有几个可用的餐厅数check$(( ${RANDOM} * ${eatnum} / 32767 1 ))
echo your may eat ${eat[${check}]}立刻执行看看你就知道该吃啥了非常有趣吧不过这个例子中只选择一个样本不够看如果想要每次都秀出 3 个店家呢 而且这个店家不能重复喔重复当然就没啥意义了所以你可以这样作
[dmtsaistudy bin]$ vim what_to_eat-2.sh
#!/bin/bash
# Program:
# Try do tell you what you may eat.
# History:
# 2015/07/17 VBird First release
PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
eat[1]卖当当汉堡
eat[2]肯爷爷炸鸡
eat[3]彩虹日式便当
eat[4]越油越好吃大雅
eat[5]想不出吃啥学餐
eat[6]太师父便当
eat[7]池上便当
eat[8]怀念火车便当
eat[9]一起吃泡面
eatnum9
eated0
while [ ${eated} -lt 3 ]; docheck$(( ${RANDOM} * ${eatnum} / 32767 1 ))mycheck0if [ ${eated} -ge 1 ]; thenfor i in $(seq 1 ${eated} )doif [ ${eatedcon[$i]} $check ]; thenmycheck1fidonefiif [ ${mycheck} 0 ]; thenecho your may eat ${eat[${check}]}eated$(( ${eated} 1 ))eatedcon[${eated}]${check}fi
done透过随机数、数组、循环与条件判断你可以做出很多很特别的东西还不用写传统程序语言试看看挺有趣的呦
19.5 shell script 的追踪与 debug
scripts 在执行之前最怕的就是出现语法错误的问题了那么我们如何 debug 呢有没有办法不需要透过直接执行该 scripts 就可以来判断是否有问题呢呵呵当然是有的我们就直接以 bash 的相关参数来进行判断吧
[dmtsaistudy ~]$ sh [-nvx] scripts.sh
选项与参数
-n 不要执行 script仅查询语法的问题
-v 再执行 script 前先将 scripts 的内容输出到屏幕上
-x 将使用到的 script 内容显示到屏幕上这是很有用的参数# 范例一测试 dir_perm.sh 有无语法的问题
[dmtsaistudy ~]$ sh -n dir_perm.sh
# 若语法没有问题则不会显示任何信息
# 范例二将 show_animal.sh 的执行过程全部列出来
[dmtsaistudy ~]$ sh -x show_animal.sh PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/binexport PATHfor animal in dog cat elephantecho There are dogs....
There are dogs....for animal in dog cat elephantecho There are cats....
There are cats....for animal in dog cat elephantecho There are elephants....
There are elephants....请注意上面范例二中执行的结果并不会有颜色的显示鸟哥为了方便说明所以在 号之后的数据都加上颜色了 在输出的讯息中在加号后面的数据其实都是指令串由于 sh -x 的方式来将指令执行过程也显示出来 如此用户可以判断程序代码执行到哪一段时会出现相关的信息这个功能非常的棒透过显示完整的指令串 你就能够依据输出的错误信息来订正你的脚本了
熟悉 sh 的用法将可以使你在管理 Linux 的过程中得心应手至于在 Shell scripts 的学习方法上面需要『多看、多模仿、并加以修改成自己的样式』 是最快的学习手段了网络上有相当多的朋友在开发一些相当有用的 scripts 若是你可以将对方的 scripts 拿来并且改成适合自己主机的样子那么学习的效果会是最快的呢
另外我们 Linux 系统本来就有很多的服务启动脚本如果你想要知道每个 script 所代表的功能是什么 可以直接以 vim 进入该 script 去查阅一下通常立刻就知道该 script 的目的了。举例来说我们之前一直提到的 /etc/init.d/netconsole 这个 script 是干嘛用的 利用 vim 去查阅最前面的几行字他出现如下信息
# netconsole This loads the netconsole module with the configured parameters.
# chkconfig: - 50 50
# description: Initializes network console logging
# config: /etc/sysconfig/netconsole意思是说这个脚本在设定网络终端机来应付登入的意思且配置文件在 /etc/sysconfig/netconsole 设定内 所以你写的脚本如果也能够很清楚的交待那就太棒了
19.6 what_to_eat-2.sh debug结果解析
[rootnode-135 bin]# sh -x what_to_eat-2.shPATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/binexport PATHeat[1]卖当当汉堡eat[2]肯爷爷炸鸡eat[3]彩虹日式便当eat[4]越油越好吃大雅eat[5]想不出吃啥学餐eat[6]太师父便当eat[7]池上便当eat[8]怀念火车便当eat[9]一起吃泡面eatnum9 #店家总数eated0 #默认while循环参数0[ 0 -lt 3 ] #第一次while循环 eated0check8 #获取的随机选择为8即eat[8]怀念火车便当mycheck0 #区别重复的参数为0默认值[ 0 -ge 1 ] #进入第一个if判断条件不符结束该判断[ 0 0 ] #进入第二个if判断条件符合执行该判断echo your may eat 怀念火车便当 #打印选择
your may eat 怀念火车便当eated1 #while循环参数1eatedcon[${eated}]8 #已选店家数组加入已选值此时eatedcon[1]8[ 1 -lt 3 ] #第二次while循环 eated1check9 #获取的随机选择为9即eat[9]一起吃泡面mycheck0 #区别重复的参数仍为0[ 1 -ge 1 ] #进入第一个if判断条件符合执行该判断seq 1 1 #第一个for的循环序列1到1所以只能执行1for i in $(seq 1 ${eated} )#第一个for循环[ 8 9 ] #for循环中的if判断是否重复本次不重复结束循环[ 0 0 ] #进入第二个if判断条件符合执行该判断echo your may eat 一起吃泡面 #打印选择
your may eat 一起吃泡面eated2 #while循环参数1eatedcon[${eated}]9#已选店家数组加入已选值此时eatedcon[1]8eatedcon[2]9[ 2 -lt 3 ]#第三次while循环 eated2check1 #获取的随机选择为1即eat[1]卖当当汉堡mycheck0 #区别重复的参数仍为0[ 2 -ge 1 ] #进入第一个if判断条件符合执行该判断seq 1 2 #第一个for的循环序列1到2所以能执行1,2for i in $(seq 1 ${eated} )#第一个for循环的第一次共2次[ 8 1 ] #for循环中的if判断是否和已选店家数组eatedcon[1]内容重复本次不重复结束判断for i in $(seq 1 ${eated} )#第一个for循环的第二次共2次[ 9 1 ] #for循环中的if判断是否和已选店家数组eatedcon[2]内容重复本次不重复结束判断for循环结束[ 0 0 ] #进入第二个if判断条件符合执行该判断echo your may eat 卖当当汉堡 #打印选择
your may eat 卖当当汉堡eated3 #while循环参数1eatedcon[${eated}]1 #已选店家数组加入已选值此时eatedcon[1]8eatedcon[2]9eatedcon[3]1[ 3 -lt 3 ] #第三次while循环 eated3此时已不满足while循环条件结束while循环整体代码执行结束该系列目录 -- 【BASH】回顾与知识点梳理目录