首页 > 系统相关 >Shell中的控制语句

Shell中的控制语句

时间:2023-04-15 17:34:01浏览次数:36  
标签:语句 控制 Shell echo sh done command 循环

 任何复杂结构的程序都可以由顺序、分支、循环三种结构实现。

    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

相关文章

  • shell命令--字符串截取
    shell截取字符串通常有两种方式:截取指定长度的字符串和截取指定模式的字符串。1.截取指定长度的字符串这种方式除了需要指定起始位置还需要指定截取长度。按起始位置可以分为从左边开始或者从右边开始。a.从左边开始截取${string:start:length}其中,string是要截取的字符......
  • shell命令--重定向
    0.从终端输入一个命令时,通常会将该命令的结果输出到终端。例如,在终端执行 pwd 命令会在屏幕上显示当前目录:#pwd/root大多数UNIX系统中,命令通常从一个叫标准输入的地方读取输入。同样,命令通常将其输出写入到标准输出。标准输入和标准输出默认情况下都是终端。那如果想......
  • Shell编程自动化之Shell编程基础
    一、Shell可以用来做什么1.自动化批量系统初始化程序;2.自动化批量软件部署程序;3.应用程序管理;4.日志分析处理程序;5.自动化备份恢复程序;6.自动化信息采集及监控程序;7.自动化管理程序;二、Shell概述1.Shell是操作系统的外壳,是用户操作系统的命令接口,是一个介于用户和系统内核......
  • linux shell编程作业
    使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub,b_sub子目录下的所有C程序文件及其目标文件的列表。dirlst="a_subb_sub"foriin$dirlstdocd$HOME/$ils-l*.cdone编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及......
  • bash shell 无法使用 perl 正则
      哈喽大家好,我是咸鱼。今天跟大家分享一个关于正则表达式的案例,希望能够对你有所帮助案例现象前几天有一个小伙伴在群里求助,说他这个shell脚本有问题,让大家帮忙看看   可以看到,这个脚本首先将目标文本文件的名字当作该脚本的第一个参数($1)传递进去,然后查看这个文本......
  • 访问权限控制
      面向对象的核心思想之一就是封装,只把有限的方法和成员公开给别人,这也是迪米特法则的内在要求,使外部调用方对方法体的实现细节知道得尽可能少。如何实现封装呢?需要使用某些关键字来限制类外部对类内属性和方法的随意访问,这些关键字就是访问权限控制符。  JAVA中的访问权限包......
  • Shell的变量
    1)Shell变量的名字可以由数字、字母和下划线组成,并且只能以字母或者下划线开头,如u_1,a12。    Shell变量有环境变量和用户自定义变量两种类型。在使用变量时变量名前加“$”。Shell的环境变量用来保存系统状态或环境参数的变量。Shell的系统变量是一种特殊的环境变量,主要......
  • shell练习3
    1.你需要打印一个给定的数字的反序,如输入10572,输出27501,如果没有输入数据,应该抛出错误和使用脚本说明。   2.写出SHELL函数RevertInput,函数必须获取三个参数,然后将三个参数倒序echo打印出来,函数必须检查参数个数的合法性,如果参数非法,打印”Illegalparameters”,对于下面的......
  • [PLC]三菱QD77MS16简易运动模块同步控制范例
    三菱QD77MS16简易运动模块同步控制范例三菱QD77MS16简易运动模块同步控制范例【详细讲解】QD77MS16是三菱新推出的一款简易型的运动控制模块。相对于普通定位模块具有控制轴数多(最多16轴),无电磁干扰(伺服光纤网络),支持同步控制,凸轮控制等优点。下面,海蓝机电将以实例来说明软件组态方......
  • m基于Simulink的自适应模糊控制器设计与仿真实现
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要模糊自适应控制器同时结合自适应控制和模糊控制,形成具有自适应的功能的控制系统。模糊自适应控制不要求控制对象具有精确的数学模型,并且还巧妙的引入了自适应律以方便实时的去学习被控对象所具有的各种动态特性,然......