任何复杂结构的程序都可以由顺序、分支、循环三种结构实现。
Shell中的控制语句主要分为两大部分:一个是条件测试与判断语句,另一个是循环结构的控制语句。
条件控制语句
1)if语句
①无分支条件语句:if-then结构
if [condition]
then
commands
……
last -command
fi
②二分支条件语句:if-then-else结构
if [condition]
then
true -command
……
last-true-command
else
false-command
last-false-command
fi
③多分支条件语句:if-then-elif结构
if [conditlon_1]
then
command_l
elif [condition_2]
then
command_2
elif[condition_3]
then
command_3
……
else
command_n
fi
2) Case语句 Case-in结构。
Case语句的语法为:
case word in
pattern-1)patl-listl;;
pattern-2)pat2-list2;;
……
*)default -list;;
esac
Word是与case中各匹配模式进行比较的变量,Pattern-1、Pattarn-2是匹配模式。每个匹配模式命令的结束用“;;”符表示,类似与C语言中使用的break语句的功能(case结构本身没有break语句)。
在shell的条件控制语句中可以使用统配符,*”可以匹配任何多个字符的字符串,“?”可以匹配任意单一字符。
例:假设有一个连续运行系统,每当运行中遇到错误时,系统都创建一个错误记录文件errorfile并将错误信息写入其中。而且这个文件是按照错误出现的频率进行更新的。编写一段shell程序,根据errorfile文件产生的特性再生成一个定时错误日志文件,日志文件名为datelog。
#!/bin/sh
#例题checkerr.sh
date>>datelog
if test -r errorfile
then cat errorfile>>datelog
rm errorfile
else echo "No error this hour.">>datelog
fi
例1:向指定的文件中添加信息。
#!/bin/sh
#filename:append.sh
case $# in
1)cat>>$1;;
2)cat>>$2<$1;;
*)echo ‘usage:append.sh [from] to’ ;;
esac
程序名为append.sh,输入下列命令:
$append.sh file1 或 $append.sh fils1 file2
$#=1时,程序执行时从标准输入流中获取文本,将接受的内容以添加方式存入文件file1中。
$#=2时,程序会执行第二条匹配语句,完成将file2的文本增加到file1中的操作。
例2:编写一段shell程序,根据执行时获取的当前时间显示出不同的问候信息。
#!/bin/sh
#例题wh.sh
#case结构
hour=`date +%H`
case $hour in
0[1-9]|1[01])echo “Good morning!”;;
1 [234567])echo “good afternoon!”;;
*)echo “good evening!”;;
esac
if 的独特条件表达式
command 命令执行成功,等于返回0 (比如grep ,找到匹配),执行失败,返回非0 (grep,没找到匹配)。
以多条command或者函数作为if 条件, 以最后一个命令执行的退出状态为其值。
if command 等价于 command+if $?
if cat tmp.txt | grep ting1; then
cat 111-tmp.txt | grep ting1
if [ $? -eq 0 ]
then
关系运算
if [ $a = q -o $a = Q ]
if test $a -gt -1 && test $a -lt 101
if [ $a -gt -1 ] && [ $a -lt 101 ]
if 的独特条件表达式
[[ expr ]] 是bash中真正的条件判断语句,其语法更符合编程习惯 (比如 &&, || 的用法),
在 [[ ]] 中 故意传字符串给 -eq 也应该像 test 一样报错,但是显然bash实现中直接把非整数的字符串直接转换成了 0 ,任何需要整数,但是提供的确又是其他不能转换成整数的字符串,都变成了0。
这应该是bash实现中的没有对 [[ ]] 中 -eq 操作符两边的内容进行检查导致的。
菜单的构造
select var in menu-item;do command; done
select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。select语句的特征主要有:没有echo指令,自动用1、2、3、4列出菜单、没有 read指令,自动输入、没有赋值指令,自动输入数字后,赋值字符串给变量。
菜单的构造
select var in menu-item;do command; done
例:利用select语句构造菜单
#!/bin/sh
echo "please input your choice:"
select fruit in "apple" "orange" "banana" "quit"
do
if [ $fruit = "quit" ]
then exit
fi
echo "your choice is $fruit"
done
循环语句
1)for循环:for-in-done结构
for循环的语法格式为:
for variable in list-of -values
do command
……
last -command
done
shell扫描list-of-values,将其中的第一个字存在循环变量(variable)中,然后执行do与done之间的命令(即循环体)。再将第二个字保存在循环变量(variable)中并再次执行循环体,依次循环。
注意:List-of-values包含着循环体中命令被执行的次数,同时还要将循环变量中存放的内容一一列出,这是与其他语言的循环语句使用不同的地方。bash支持{n..m}的写法。
例:列出用户注册目录下的cc和work子目录中所有C语言源程序文件。
#!/bin/sh
#显示*.C文件
cd $HOME
for dir in cc work
do echo “….in $dir….”
cd $dir
for file in *.[c]
do ls -l $file
done
cd
done
2) while循环:while-do-done结构
语法结构为:
while [condition]
do
commands
…
last-command
done
可以把while循环语句看作是for循环和if条件语句的功能组合形式,在完成while循环时,通常首先要执行一个test命令,根据test的执行结果决定下一步循环体是否还要执行。如果test的返回值为真时,执行do-done中的内容;否则不执行循环体并结束循环过程。
注意:在while循环中要设计好condition的出口状态,它应是能够在程序执行中被改变的,否则会出现程序的死循环状况。
例:
#!/bin/sh
#例while循环wh.sh
while[-r abc.c]
do
echo ‘before sleep……’
sleep 5
echo ‘sleep done’
done
因为此程序在判定了文件abc.c存在并可读后,就输出“Before sleep.....”,停留5秒后再输出"sleep done",然后反复循环执行这两条输出语句,所以直到文件abc.c被删除或取消了读取权限以前,该程序都不能跳出循环,是一种死循环的过程。
3)until循环:until-do-done结构
只要循环条件为假(非0值),就执行循环体。格式如下:
until [condition]
do
commands
……
last-command
done
如果在第一次执行时,循环条件就为真,则循环体可能会永远不执行。必须在程序中设置能使条件为“真”的因素(注意:对while来讲是判别条件为“假”,而until是判别条件为真),否则该循环会成为一个无限循环的死循环程序。如果出现这种问题,用户必须用系统的kill命令杀死这个进程以终止循环。
for语句用来实现循环,还有其他常见3种形式写法:
列表for循环语句
不带列表的for循环语句
类似C语言的for循环语句
1.列表for循环语句,格式如下:
for var in {list}
do
Loop body
done
如:
for country in {'China','America','England','Japan'}
do
echo $country
done
2.不带列表的for循环语句,格式如下:
for var
do
Loop body
done
如:for argument
do
echo "$argument"
done
执行:sh test16.sh 1 2 3
3.类似C语言的for循环语句,格式如下: for ((expression1;expression2;expression3))
do
Loop body
done
如:
for ((i=1;i<100;i++))
do
let "sum+=i"
done
break语句
break语句用来结束循环,基本语法格式如下:
break n
break 命令后面的整数n表示要提出n层循环,默认值为1。
continue语句
continue语句表示不再运行循环体中continue后面的语句,开始下次循环。基本语法格式如下:
continue n
continue命令后面的整数n表示要提出n层循环,默认值为1。
例:编一个程序,查看指定的用户是否登录到系统上。如果没有,则在他登录时进行报告。
#程序uon:查询用户“***”是否在系统中
until who|grep”$1”>/dev/null
do
sleep 30 #等待30秒
done
echo -e “\07\07$1 is logged on” #07表示一次蜂鸣声
#当用户登录时用于提示
exit 0
程序中只要循环条件为“真”,until循环就终止。如果grep命令未能在who命令送给它的用户列表中发现指定的用户ID,则循环条件保持为假(不为0),并且until循环继续执行循环体的“sleep“指令。
上例程序运行存在一个问题,如使用者一直没登录,则使用者也无法使用该终端。合理地解决办法是将本程序放后台运行。
$uon lili& /*后台运行该程序检查用户lili是否登录到系统*/
4583 /*系统显示进程ID*/
$ /*系统显示shell命令提示符,现可以做其他事情了*/
如果lili登录,系统会用两声蜂鸣和显示信息"lili is on the system”通知使用者lili用户已经登录了。
expr命令
expr命令是对shell变量进行算术运算的操作,因为shell变量都是字符型变量,对这种变量简单的进行四则运算不能达到预期的效果,必须使用expr命令做四则运算。在程序中是将表达式作为一种实参引用的。如:
$count =0 /*首先给变量count赋值*/
$count =count+1 /*试图完成count+l再赋给count的操作*/
$echo $count /*查看操作后的效果*/
系统显示:0+1
$count = “`expr $count + 1`”
$echo $count
系统显示:1
使用这一命令时为避免出现错误,在命令书写中要将操作数与运算符之间用空格分开,如果运算符是乘号或除号时,对它们要做转义处理,例如,\*,/ \就是表示对符号“*”和“\”的转义。
其他:a=$[$a+1] 即用$[] 来完成算术运算。
另外在编写循环语句时,也可以使用break和continue语句来改变for和while循环的执行顺序。它们的引用方法与C语言中的规定相似,即break表示退出当前所在的整个循环。continue表示结束本轮循环,转到下一轮循环的开始。
其他:
a=$(expr 3 + 4)
b=$( date )
()中写命令
a=$[$a+1] 即用$[] 来完成算术运算。
[]中写算术表达式
let c=12 只能对变量赋数值,字符赋值一律为0
若需要将标准输入的值存入到变量中,可用read命令.例:
# the read command example
echo “enter you name:\c”
read name
echo “your name is $name”
read 命令中的参数说明:
read [word1][word2][rest]
存放方式为:第一,第二,其余参数
# test read command,filename:read_test
echo “give me a long sentence:\c”
read word1 word2 rest
echo “$word1\n $word2\n $rest”
echo “end of my act”
运行: $ read_test
give me a long sentence:
输入:let’s test the read command.
输出:let’s
test
the read command
end of my act
编写shell程序许多时候需要与用户交互,因此输出格式也很重要。几个问题要注意:
1)shell 程序执行可能会有错,若不做重定向都会输出到标准输出上,应注意将不必要的信息输出到垃圾文件中。例:
cp filea fileb >/dev/null
2) 用echo命令可完成向用户显示信息,例如:
$ echo “Mary had a little lamb”
echo命令也可以实现格式化输出,描述如下。
在echo 命令中可使用的字符及含义:
\b Backspace(回退一个字符)
\c 显示输出信息后不换行
\f 在终端的屏幕开始处进行显示
\n 换行符
\r 回车符
\t 显示制表符(Tab)
\v 垂直制表符
注:linux中使用这些格式显示时需加“-e”选项。
shell程序的调试方法
Shell程序是一种解释执行语言,其执行是逐行完成的,当程序中语句有语法错误时,对未执行到的语句,系统并不进行提示。但在编程中通常要对程序的整体正确性进行调试和验证:
1)交互式调试:对命令或语法可先用命令进行验证,然后再引用到shell编程中。
2)在编辑过程中不断调试执行所编辑的程序:UNIX中可以打开多个窗口工作,可以在一个打开的窗口中进行vi的程序编辑,在另一个打开的窗口中执行并观察刚编辑的程序的执行结果,判断是否正确,逐步完成整个程序的调试。
3)使用-v、-x选项对shell程序进行跟踪:
-v—完成详细跟踪,将逐行读入执行的命令,并在标准输出上显示,然后执行此语句,直到有语法错误时停止执行过程。
-x—实际命令运行的跟踪,首先显示经过变量替换后的命令行内容,然后再执行它。
例:对一个shell程序test.sh进行跟踪的过程如下:
假设,test.sh中只包括两条语句:
date
echo $PATH
若采用-v选项跟踪时输入命令:
$sh –v test.sh
执行结果为:
date
Fri Aug 8:16:00 Prc 2001
Echo $PATH
/usr/bin:/usr/ucb/bin:/home/chr/bin
例:编写一个shell程序on.sh,判断指定的用户是否注册,若是则拷贝一个关于用户信息的文件,否则显示一条提示信息。程序如下:
#on.sh
echo “type in your logname :\c” #\c新行终止符
read user
if
grep $user /etc/passwd>/tmp/null
who –u | grep $user
then
echo “$user has logged in the system.”
cp /tmp/null tmp1
rm /tmp/null
else
echo “$user has not logged in the system.”
fi
可能运行结果:
$sh ./on
type in your logname:chen↙
chen yyt04 Mar 12 14:32 0:03 453
chen has logged in the system.
$cat tmp1
chen:*:200:50::/usr/chen:/bin/sh
标签:语句,控制,Shell,echo,sh,done,command,循环 From: https://blog.51cto.com/u_16058240/6192386