本篇博客将介绍下面四点:
1、两种控制选择结构:
if(根据出口状态判断)、case(根据变量选择)
2、4种循环结构:
for、while、until、select
上面四种循环结构可以分为三类:
根据命令出口状态检测:while、until
根据给定的参数来循环执行:for
根据用户指定的参数来循环执行(和用户交互较好):select
3、两种用于打断循环体的命令:break、continue
4、Shell函数
顺便说明在控制条件中经常使用的测试,数值比较和一些概念:
test命令用于比较、判断、测试文件等:点击打开链接
expr、let等数值计算的命令:点击打开链接
出口状态和标准输出的区别:点击打开链接
正文开始:
if和case均是用于判断选择的结构。
if 和case的判断有一点不同。if是根据命令的出口状态来判断,case是变量的匹配。
每一个if后面都必须跟一个then
if结构:
①
if command #检测的是这个command的出口状态,而不是标准输出
then
command-list
fi
②
if command
then
command-list
else
command-list
fi
③
if condition
then
if condition #嵌套了一个if结构
then
Command-list
fi
fi
④
if condition
then
command-list
elif condition2 #使用elif(else if)子语句进行条件转移
then
command-list
else
command-list
fi
这个结构就是C语言中的:
if
else if
else if
……
else
脚本代码:
if eo a #eo a命令错误,所以命令出口状态为非0,跳到elif
then
echo chenhaojie
elif ls -y >test1 #ls -y >test1 命令ls -y 结构错误,标准输出重定向到test1,跳到else
then
echo Hytera
else
echo WUST #最终会输出这一句
fi
case “$variable” in
pattern1)
command-list ;;
pattern2)
command-list ;;
……
patternN)
command-list ;;
esac
当然,"$variable"可以是任意变量、字符串、数值等。
所以,$variable的位置可以引用变量、命令输出和命令出口状态等等。
$variable 、$(command)、command之后,通过$?、$$……引用(内部变量的使用:点击打开链接)等等。
read a
case $a in
1) echo 1;;
2) echo 2;;
*) echo what;;
esac
注意:read只接收标准输入的数据,不接收参数。
标准输入和参数的区分:点击打开链接
while 和 until都是根据命令输出状态来检测的;
for 是根据给定的参数来循环,每循环一次就给一次数据,直至数据输入完;
select 是根据用户输入选项来从给定参数中选择。
四种循环结构的结构都是:
do
……
done
for var in arg1 arg2 …… argN
do
command-list
done
工作方式:每循环一次,var被重新赋值一次。var赋值的来源就是从给定的参数列表[arg1 arg2 …… argN]中依次取一个,赋给变量var。
在command-list中,可以引用并使用var的值。
基本结构:
while [ condition-is-true ]
do
command-list
done
工作方式:每一次根据while后command的出口状态来进行判断,如果出口状态为真(返回出口状态为0),则进行循环操作。
基本结构:
until [ condition-is-true ]
do
command-list
done
工作方式:根据until后command的出口状态进行判断,如果出口状态为假(非0),则进行循环操作。
基本结构:
PS3=’string’ #(给用户提示的字符串)点击打开链接
select var in list
do
command-list
break
done
工作方式:根据用户的输入,来选择给var的值,然后执行命令串。之后就break。如果不加break,则select会一直循环。
注意:select 后面的参数可以在输入时省略。省略的话,则需要其大结构的函数或脚本的命令行中提供参数,以作为select的参数表。
脚本功能:1、2、3、4这四个数字可以组成多少个无重复的三位数的数值。
但是这个问题,只是用来熟悉循环操作,在linux运维中,这种编程并没有什么用。因为在运维中,使用来对系统进行操作的,而不是进行数值计算的。
脚本名称:sum
代码:
i=0
j=1
k=0
n=0
PS3="请输入你的选择:1是处理2是不处理"
select a in 1 2
do
if [[ $a -eq 1 ]]
then
while [[ $j < 5 ]]
do
let j=j+1
for i in 1 2 3 4
do
for k in 1 2 3 4
do
case $k in
1|2|3|4) let n=n+1;;
*) echo error ;;
esac
done
done
done
elif [[ $a -eq 2 ]]
then
break
else
echo error
fi
done
echo $n
输出结果:64
结构分析:包含三层循环。外层变量j的while循环,是用来控制三个数字中的第一个数字,第一层for结构是用来控制三个数字中的第二个数字;最内层的for结构是用来控制三个数字中的第三个数字。case结构是用来计数的,同时增加了一个检测,以防出现除了1 2 3 4以外的不可控情况(其实比较多余)
脚本问题总结:在调试时,由于j的初始状态给的是0,所以,外层循环了五次,5*4*4得到了80次的输出。
调试方式:于是调试脚本,通过命令bash –x sum 2>test.txt(注意,调试信息输出的是stderr,虽然在《shell脚本攻略》这本书中说它是stdout,实测是stderr)
结果:通过调试,发现外层循环了五次,这当然不是应该的状态。改过之后,输出64次:4*4*4
介绍一下break和continue的用法和区别:
作用对象:用于循环结构的退出。
区别:break是跳出循环;continue是用于跳过这一次循环
用法:用法和c语言中的break和continue的用法一样。
函数在各种语言中也是必不可少的一个结构
① 存在一组需要重复执行的处理动作
② 针对不同参数,希望能够获得相应的返回值
①
function_name( )
{
Command-list
}
②
function function_name( )
{
Command-list
}
相比之下,第2种就比较多余。
在调用函数之前,必须首先对函数进行定义。所以函数定义一般放在脚本首行,后者靠前的位置。但是函数只有被调用才会执行,函数定义时是不会执行函数的。
① 定义函数时注意:函数名必须和左圆括号连在一起
② Shell函数的结束:可以使用return [n] 来结束一个shell函数,来返回一个设定的数值n.
也可以直接return,返回的就是截止到return那里的,最后一条命令的出口状态(不要用exit,它是用于结束一个脚本的命令)。
当然也可以不用return。可以直接将函数中执行的最后一个命令的出口状态,作为返回值。
③ shell函数的调用:shell函数调用时,直接写出函数的名字,然后在后面给出必要的参数,各部分用空格分隔,不能使用圆括号。