Shell脚本编写基础_第1页
Shell脚本编写基础_第2页
Shell脚本编写基础_第3页
Shell脚本编写基础_第4页
Shell脚本编写基础_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Shell本身是一个用C语言编写的程序,它是用户使用语言,又是一种程序设计语言。作为命令语言,Linux的桥梁。Shell既是一种命令它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统的关键。可以说,shell使用的熟练程度反映了用户对Linux使用的熟练程度。一、什么是s

2、hell当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shell(外壳)0000那么,shell是什么呢?确切一点说,shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动、挂起、停止甚至是编写一些程序。当用户使用Linux时是通过命令来完成所需工作0。一个命令就是用户和shell之间对话的一个基本单位,它是由多个字符组成并以换行结束的字符串。shell解释用户输入0命令,就象DOS里0所做的一样,所不同的是,在DOS中,只有一个,而在Linux下比较流行的shell0000,每个s

3、hell都各有千秋。一般的Linux系统都将bash作为默认的shellO二、几种流行0shell00000shell0ash、bash、ksh、csh、zsh等,你可以用下面的命令来查看你自己的shell类型:#echo$SHELL$SHELL是一个环境变量,它记录用户所使用0shell类型。你可以用命令:#shell-name来转换到别的shell,DOshell-name是你想要尝试使用的shell0名称,如ash等。这个命令为用户又启动了一个shell,这个shell在最初登录的那个shell之后,称为下级的shell或子shell。使用命令:$exit可以退出这个子shell。000

4、00shell0原因在于它们各自都有自己的特点,下面作一个简单的介绍:ashashshell是由KennethAlmquist编写0,Linux中占用系统资源最少0一个小shell,它只包含24个内部命令,因而00起来很不方便。2.bashbash是Linux系统默认000shell,它由BrianFox和ChetRamey共同完成,是BourneAgainShell0缩写,内部命令一共04000Linux00它作为默认0shell是因为它有诸如以下0特色:000000DOS下面的doskey0功能,用方向键查阅和快速输入并修改命令。自动通过查找匹配0方式给出以某字符串开头0命令。包含了自身0

5、帮助功能,你只要在提示符下面键入help就可以得到相关0帮助。kshksh是Kornshell0缩写,由EricGisin编写,共有42条内部命令。该shell最大0优点是几乎和商业发行版0ksh完全兼容,这样就可以在不0花钱购买商业版本0情况下尝试商业版本0性能了。cshcsh是Linux比较大的内核,它由以WilliamJoy为代表的共计47位作者编成,共有52个内部命令。该shell其实是指向/bin/tcsh这样的一个shell,也就是说,csh其实就是tcsh。zchzch是Linux最大的shell之一,由PaulFalstad00,0084个内部命令。如果只是一般的用途,是没有必

6、要安装这样的shell的。3.shell程序设计(基础部分)其实作为命令语言交互式地解释和执行用户输入的命令只是shell0000000,shell还可以用来进行程序设计,它提供了定义变量和参数的手段以及丰富的程序控制结构。使用shell编程类似于DOS中的批处理文件,称为shellscript,又叫shell程序或shell命令文件。l.shell基本语法shell的基本语法主要就是如何输入命令运行程序以及如何在程序之间通过shell的一些参数提供便利手段来进行通讯。(1)输入输出重定向在Linux中,每一个进程都有三个特殊的文件描述指针:标准输入(standardinput,文件描述指针为

7、0)、标准输出(standardoutput,文件描述指针为1)、标准错误输出(standarderror,文件描述指针为2)。这三个特殊的文件描述指针使进程在一般情况下接收标准输入终端的输入,同时由标准终端来显示输出,Linux同时也向使用者提供可以使用普通的文件或管道来取代这些标准输入输出设备。在shell中,使用者可以利用“”和“”。(2)用户定义的变量用户可以按照下面的语法规则定义自己的变量:变量名=变量值要注意的一点是,在定义变量时,变量名前不应加符号“$”,在引用变量的内容时则应在变量名前加“$”;在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用

8、双引号括起来。在编写shellODD,为了使变量名和命令名相区别,示。建议所有的变量名都用大写字母来表有时我们想要在说明一个变量并对它设定为一个特定值后就不在改变它的值,的命令来保证一个变量的只读性:readly变量名在任何时候,建立的变量都只是当前shell的局部变量,这可以用下面所以不能被shell运行的其他命令或shell程序所利用,其格式为:export命令可以将一局部变量提供给shell执行的其他命令使用,export变量名也可以在给变量赋值的同时使用export变量名=变量值使用export说明的变量,在(3)位置参数位置参数是一种在调用输入的参数。位置参数之间用空格分隔,expo

9、rt命令:shell以后运行的所有命令或程序中都可以访问到。shell程序的命令行中按照各自的位置决定的变量,shell取第一个位置参数替换程序文件中的二个替换$2,依次类推。$0是一个特殊的变量,所以,$0不是一个位置参数,在显示当前所有的位置参数时是不包括(4)预定义变量它的内容是当前这个预定义变量和环境变量相类似,也是在shell一开始时就定义了的变量,是在程序名之后$1,第shell程序的文件名,$0的。所不同的是,用户只能根据shell的定义来使用这些变量,而不能重定义它。所有预定义变量都是由$符和另一个符号组成的,常用的shell预定义变量有:$#:位置参数的数量$*:所有位置参数

10、的内容$?:命令执行后返回的状态$:当前进程的进程号$!:后台运行的最后一个进程号$0:当前执行的进程名其中,“$?”用于检查上一个命令执行是否正确令正确执行,任何非0值表示命令出错)。“$”变量最常见的用途是用作临时文件的名字以保证临时文件不会重复。(5)参数置换的变量shell提供了参数置换能力以便用户可以根据不同的条件来给变量赋不同的值。(在Linux中,命令退出状态为0表示该命参数置换的变量有四种,这些变量通常与某一个位置参数相联系,决定变量的取值,它们的语法和功能分别如下。a.变量二$参数word:如果设置了参数,即这种变量的值等于某一个参数的值,如果该参数没有设置,则变量就等于根据

11、指定的位置参数是否已经设置类则用参数的值置换变量的值,否则用word置换。word的值。b.变量=$参数=word:如果设置了参数,则用参数的值置换变量的值,否则把变量设置成word然后再用word替换参数的值。注意,位置参数不能用于这种方式,因为在shell程序中不能为位置参数赋值。c.变量=$参数?word:如果设置了参数,则用参数的值置换变量的值,否则就显示并从shell中退出,如果省略了word,则显示标准信息。这种变量要求一定等于某一个参word数的值,如果该参数没有设置,就显示一个信息,然后退出,因此这种方式常用于出错指示。d.变量=$参数+word:如果设置了参数,则用word置

12、换变量,否则不进行置换。所有这四种形式中的“参数”既可以是位置参数,也可以是另一个变量,只是用位置参数的情况比较多。shell提供了用来控制程序执行流程的命令,包括条件分支四、shell程序设计的流程控制和其他高级程序设计语言一样,和循环结构,用户可以用这些命令建立非常复杂的程序。与传统的语言不同的是,shell用于指定条件值的不是布尔表达式而是命令和字符串。1.test测试命令test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试,其测试符和相应的功能分别如下:(1)数值测试:-eq:等于则为真-ne:不等于则为真gt:大于则为真-ge:大于等于则为真-lt:小于则为

13、真-le:小于等于则为真(2)字符串测试:=:等于则为真!=:不相等则为真-z字符串:字符串长度伪则为真-n字符串:字符串长度不伪则为真(3)文件测试:-e文件名:如果文件存在则为真-r文件名:如果文件存在且可读则为真-w文件名:如果文件存在且可写则为真-x文件名:如果文件存在且可执行则为真-s文件名:如果文件存在且至少有一个字符则为真-d文件名:如果文件存在且为目录则为真-f文件名:如果文件存在且为普通文件则为真-c文件名:如果文件存在且为字符型特殊文件则为真-b文件名:如果文件存在且为块特殊文件则为真另外,Linux还提供了与(“!”)、或(“0)、非(“a”)三个逻辑操作符用于将测试条件

14、连接起来,其优先级为:“!”最高,“a”次之,“o”最低。同时,bash也能完成简单的算术运算,格式如下:$expression例如:var1=2var2=$var1*10+1则:var2的值为21。2.if条件语句shell程序中的条件分支是通过if条件语句来实现的,其一般格式为:if条件命令串then条件为真时的命令串else条件为假时的命令串fi3.for循环赋给变量的几个数值既可以在程序内for循环的一般格式为:var,则在in之后给出的数值将顺序var的取值将是位置参数。对变量的While循环的一般格式为:for循环对一个变量的可能的值都执行一个命令序列。以数值列表的形式提供,也可以

15、在程序以外以位置参数的形式提供。for变量名in数值列表do若干个命令行done变量名可以是用户选择的任何字符串,如果变量名是替换循环命令列表中的$var。如果省略了in,则变量每一个可能的赋值都将执行do和done之间的命令列表。4.while和until循环while和until命令都是用命令的返回状态值来控制循环的。while若干个命令行1do若干个命令行2done只要while的“若干个命令行do.done之间的“若干个命令行1”中最后一个命令的返回状态为真,2”。while循环就继续执行until命令是另一种循环结构,它和while命令相似,其格式如下:until若干个命令行1do若

16、干个命令行2doneuntil循环和while循环的区别在于:while循环在条件为真时继续执行循环,而until则是在条件为假时继续执行循环。ShellDODOtrue和false两条命令用于建立无限循环结构的需要,它们的返回状态分别是总为0或总为非0case条件选择辻条件语句用于在两个选项中选定一项,而case条件选择为用户提供了根据字符串或变量的值从多个选项中选择一项的方法,其格式如下:casestringinexp-1)若干个命令行1;exp-2)若干个命令行2;*)其他命令行esacshell通过计算字符串string的值,将其结果依次和表达式exp-1、exp-2等进行比较,直到找

17、到一个匹配的表达式为止,如果找到了匹配项则执行它下面的命令直到遇到一对分号(;)为止。在case表达式中也可以使用shell的通配符(“*”、“?”、“”)。通常用“*”作为case命令的最后表达式以便使在前面找不到任何相应的匹配项时执行“其他命令行”的命令。无条件控制语句break和continuebreak用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。函数定义在shell中还可以定义函数。函数实际上也是由若干条shell命令组成的,因此它与shell程序形式上是相似的,不同的是它不是一个单独的

18、进程,而是shell程序的一部分。函数定义的基本格式为:functionname若干命令行调用函数的格式为:functionnameparam1param2shell函数可以完成某些例行的工作,而且还可以有自己的退出状态,因此函数也可以作为f、while等控制结构的条件。在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时shell将把这些参数分别赋予相应的位置参数$1、$2、.及$*。8.命令分组在shell中有两种命令分组的方法:“()”和“”,前者当shellDO()中的命令时将再创建一个新的子进程,然后这个子进程去执行圆括弧中的命令。当用户在执行某个命令时不想让命令运行时对状态

19、集合(如位置参数、环境变量、当前工作目录等)的改变影响到下面语句的执行时,就应该把这些命令放在圆括弧中,这样就能保证所有的改变只对子进程产生影响,而父进程不受任何干扰;用于将顺序执行的命令的输出结果用于另一个命令的输入(管道方式)。当我们要真正使用圆括弧和花括弧时(如计算表达式的优先级),则需要在其前面加上转义符()以便让shell知道它们不是用于命令执行的控制所用。9.信号trap命令用于在shell程序中捕捉到信号,之后可以有三种反应方式:执行一段程序来处理这一信号接受信号的默认操作忽视这一信号trap对上面三种方式提供了三种基本形式:第一种形式的trap000shell接收到signal

20、list清单中数值相同的信号时,将执行双引号中的命令串。trapcommandssignal-listtrapcommandssignal-list为了恢复信号的默认操作,使用第二种形式的trap00:trapsignal-list第三种形式的trap00允许忽视信号:trapsignal-list注意:(1)对信号11(段违例)不能捕捉,因为shell本身需要捕捉该信号去进行内存的转储。在trap中可以定义对信号0的处理(实际上没有这个信号),shell程序在其终止(如执行exit语句)时发出该信号。在捕捉到signal-list中指定的信号并执行完相应的命令之后,如果这些命令没有将shel

21、l程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致shell程序无法终止。另外,在trap语句中,单引号和双引号是不同的,当shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若commands是用单引号括起来的话,那么shell不会对commands中的变量和命令进行替换,否则commands中的变量和命令将用当时具体的值来替换。五、运行shell00000用户可以用任何编辑程序来编写shellODD因为shell0序是解释执行的,所以不需要编译装配成目标程序,按照shell编程的惯例,以bash为例,程序的第一行一般为“

22、#!/bin/bash”,其中#表示该行是注释,叹号“!”告诉shell运行叹号之后000并用文件的其余部分作为输入,也就是运行/bin/bash并让/bin/bash去执行shell000内容。DOshell000方法有三种:(1)shshell00文件名这种方法000格式为:bashshell00000这实际上是调用一个新的bash00解释00,而把shell00文件名作为参数传递给它。新启动0shell将去读指定000,执行文件中列出000,当所有000都执行完结束。该方法的优点是可以利用shell调试功能。(2)sh格式为:bash这种方式就是利用输入重定向,使shell命令解释程序的

23、输入取自指定的程序文件。用chmod命令使shell程序成为可执行的一个文件能否运行取决于该文件的内容本身可执行且该文件具有执行权。对于shell程序,当用编辑器生成一个文件时,系统赋予的许可权限都是运行这个文件时,只需要直接键入文件名即可。在这三种运行shell000000,最好按下面的方式选择:它的正确性还没有把握时,应当使用第一种方式进行调试。应使用第三种方式把它固定下来,以后只要键入相应的文件名即可,用。六、bash000DD在编程过程中难免会出错,有的时候,调试程序比编写程序花费的时间还要多,同样如此。shell0序的调试主要是利用bash命令解释程序的选择项。调用bash-选择项s

24、hell00000几个常用的选择项是:-e:如果一个命令失败就立即退出-n:读入命令但是不执行它们-u:置换时把未设置的变量看作出错644(rw-r-r-),因此,当用户需要当刚建立一个shell00,对当一个shell程序已经调试好时,并可被另一个00所调shell00bash的形式是:-V:当读入shell输入行时把它们显示出来-X:执行命令时把命令和它们的参数显示出来上面的所有选项也可以在shell程序内部用“set-选择项”的形式引用,而“set+选择项”则可以将该部分用上面两个语句包围起来。1.未置变量退出和立即退出未置变量退出特性允许用户对所有变量进行检查,shell000执行。s

25、hell通常允许未置变量0使用,在这种情况下,变量0值为空。如果设置了未置变量退出选择项,则一旦使用了未置变量就显示错误信息,并终止000运行。未置变量退出选择项为“-u”。当shell运行时,若遇到不存在或不可执行0命令、重定向失败或命令非正常结束等情况时,如果未经重新定向,该出错信息会打印在终端屏幕上,而shell00仍将继续执行。要想在错误发生时迫使shell00立即结束,可以使用“-e”选项将shell000执行立即终止。如果引用了一个未赋值的变量就终止则将禁止该选择项起作用。如果只想对00的某一部分使用某些选择项时,2.shell程序的跟踪调试shell程序的主要方法是利用shell

26、命令解释程序的“-v”或“-x”选项来跟踪程序的执行。“-v”选择项使shell在执行程序的过程中,把它读入的每一个命令行都显示出来,而“-X”选择项使shell在执行程序的过程中把它执行的每一个命令在行首用一个“+”加上命令名显示出来。并把每一个变量和该变量所取的值也显示出来,因此,它们的主要区别在于:在执行命令行之前无“-v”则打印出命令行的原始内容,而有“-v”则打印出经过替换后的命令行的内容。除了使用shellCD-v”和“-x”选择项以外,还可以在shell程序内部采取一些辅助调试的措施。例如,可以在shell程序的一些关键地方使用echo命令把必要的信息显示出来,它的作用相当于C语

27、言中的printf语句,这样就可以知道程序运行到什么地方及程序目前的状态。七、bash的内部命令bash命令解释程序包含了一些内部命令。内部命令在目录列表时是看不见的,它们由shell本身提供。常用的内部命令有:echo、eval、exec、export、readonly、read、shift、wait和点(.)。下面简单介绍其命令格式和功能。1.echo命令格式:echoarg功能:在屏幕上打印出由eval命令格式:evalargs功能:当shell程序执行到命令,然后执行。execarg指定的字符串。eval语句时,shell读入参数args,并将它们组合成一个新的命令格式:exec命令命

28、令参数功能:当shell执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程,也就是最初的shell就终止了,所以shell程序中exec后面的语句将不再被执行。4.export=变量值shell从而让子进程继承父进程中的环命令格式:export变量名或:export变量名功能:shell000export把它的变量向下带入子境变量。但子shellODDexport把它的变量向上带入父注意:不带任何变量名的export语句将显示出当前所有的5.readonlyshell。export变量。命令格式:readonly变量名功能:将一个用户定义的shel

29、l变量标识为不可变的。不带任何参数的示出所有只读的shell变量。readonly命令将显read命令格式:read变量名表功能:从标准输入设备读入一行,分解成若干字,赋值给7.shift语句功能:shift语句按如下方式重新命名所有的位置参数变量:程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,shell0序内部定义的变量。$2成为$1,$3成为$2在并使位置参数“$#”减一,直到减到0。wait功能:是shell等待在后台启动的所有子进程结束。Wait的返回值总是真。exit功能:退出shell程序。在exit之后可有选择地指定一个数字作为返回状态。“.”(点)00

30、00:.Shell00000功能:使shell读入指定的shell程序文件并依次执行文件中的所有语句。1.Linux脚本编写基础1.1语法基本介绍1.1.1开头程序必须以下面的行开始(必须方在文件的第一行):#!/bin/sh符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。当编辑好脚本时,如果要执行该脚本,还必须使其可执行。要使脚本可执行:编译chmod+xfilename这样才能用./filename来运行1.1.2注释在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那

31、么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。1.1.3变量在其他编程语言中您必须使用变量。在shellDOO,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:#!/bin/sh#对变量赋值:a=helloworld#现在打印变量a的内容:echoAis:echo$a有时候变量名很容易与其他文字混淆,比如:num=2echothisisthe$numnd这并不会打印出thisisthe2nd,而仅仅打印thisisthe,因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我

32、们要打印的是num变量:num=2echothisisthe$numnd这将打印:thisisthe2nd环境变量由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。Shell命令和流程控制在shell脚本中可以使用三类命令:1)Unix命令:虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。常用命令语法及功能echosometext:将文字内容打印在屏幕上ls:文件列表wc-lfilewc-wfilewc-cfile:计算文件行数计算文件中的单词数计算文件中

33、的字符数cpsourcefiledestfile:文件拷贝mvoldnamenewname:重命名文件或移动文件rmfile:删除文件greppatternfile:在文件内搜索字符串比如:grepsearchstringfile.txtcut-bcolnumfile:指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut-b5-9file.txt千万不要和cat命令混淆,这是两个完全不同的命令catfile.txt:输出文件内容到标准输出设备(屏幕)上filesomefile:得到文件类型readvar:提示用户输入,并将输入赋值给变量sortfile.t

34、xt:对file.txt文件中的行进行排序uniq:删除文本文件中出现的行列比如:sortfile.txt|uniqexpr:进行数学运算Example:add2and3expr2+3find:搜索文件比如:根据文件名搜索find.-namefilename-printtee:将数据输出到标准输出设备(屏幕)和文件比如:somecommand|teeoutfilebasenamefile:返回不包含路径的文件名比如:basename/bin/tux将返回tuxdirnamefile:返回文件所在路径比如:dirname/bin/tux将返回/binheadfile:打印文本文件开头几行tail

35、file:打印文本文件末尾几行sed:Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus替换为LinuxFocus:cattext.file|seds/linuxfocus/LinuxFocus/newtext.fileawk:awk用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。catfile.txt|awk-F,print$1,$3这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如

36、下:AdamBor,34,IndiaKerryMiller,22,USA命令输出结果为:AdamBor,IndiaKerryMiller,USA2)概念:管道,重定向和backtick这些不是系统命令,但是他们真的很重要。管道(|)将一个命令的输出作为另外一个命令的输入。grephellofile.txt|wc-l在file.txt中搜索包含有”hello”的行并计算其行数。在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。写入文件并覆盖旧文件加到文件的尾部,保留旧文件内容。反短斜线使用反短斜线可以将一个命令的输出作为另

37、外一个命令的一个命令行参数。命令:find.-mtime-1-typef-print用来查找过去24ODD-mtime-2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:#!/bin/sh#Theticksarebackticks()notnormalquotes():tar-zcvflastmod.tar.gzfind.-mtimeT-typef-print3)流程控制1.ifif表达式如果条件为真则执行then后面的部分:if;thenelif;thenelsefi大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存

38、在及是否可读等等通常用来表示条件测试。注意这里的空格很重要。要确保方括号的空格。-fsomefile:判断是否是一个文件-x/bin/ls:判断/bin/ls是否存在并有可执行权限-n$var:判断$var变量是否有值$a=$b:判断$a0$b是否相等执行mantest可以查看所有测试表达式可以比较和判断的类型。直接执行以下脚本:#!/bin/shif$SHELL=/bin/bash;thenechoyourloginshellisthebash(bourneagainshell)elseechoyourloginshellisnotbashbut$SHELLfi变量$SHELL包含了登录sh

39、ell的名称,我们和/bin/bash进行了比较。快捷操作符熟悉C语言的朋友可能会很喜欢下面的表达式:-f/etc/shadow&echoThiscomputerusesshadowpasswors这里&就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。您也可以认为是逻辑运算中的与操作。上例中表示如果/etc/shadow文件存在则打印”Thiscomputerusesshadowpasswors”。同样或操作(|)在shell编程中也是可用的。这里有个例子:#!/bin/shmailfolder=/var/spool/mail/james-r$mailfolderechoCannot

40、read$mailfolder;exit1;echo$mailfolderhasmailfrom:grepFrom$mailfolder该脚本首先判断mailfolder是否可读。如果可读则打印该文件中的From一行。如果不可读则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:-打印错误信息一般函数将-退出程序我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。在下文提及。不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。casecase:表达式可以用来匹配一个给定的字符串,而不是数字。case.in.)dosomet

41、hinghere;esac让我们看一个例子。file命令可以辨别出一个给定文件的文件类型,比如:filelf.gz这将返回:ziplf.gz:gzipcompresseddata,deflated,originalfilename,lastmodified:MonAug2723:09:182001,os:Unix我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2,gzip和类型的压缩文件:#!/bin/shftype二file”$1case$ftypein$1:Ziparchive*)unzip$1;$1:gzipcompressed*)gunzip$1;$1:bz

42、ip2compressed*)bunzip2$1;*)echoFile$1cannotbeuncompressedwithsmartzip;esac您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参数值。也就是说,当我们运行:smartziparticles.zip$1就是字符串articles.zipselsectselect表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。selectvarin.;dobreakdonenow$varcanbeused下面是一个例子:#!/bin/shechoWhatisyourfavo

43、uriteOS?selectvarinLinuxGnuHurdFreeBSDOther;do这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。breakdoneechoYouhaveselected$var下面是该脚本运行的结果:WhatisyourfavouriteOS?1)LinuxGnuHurdFreeBSDOther#?1YouhaveselectedLinux4.looploop表达式:while.;dodonewhile-loop将运行直到表达式测试为真。willrunwhiletheexpressionthatwetestforistrue.关键字break用来

44、跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。(字符串用空格分隔)然后将其赋给一个变量:for-loop表达式查看一个字符串列表forvarin;dodone在下面的例子中,将分别打印#!/bin/shforvarinABC;doechovaris$vardone下面是一个更为有用的脚本#!/bin/shABC到屏幕上:showrpm,其功能是打印一些RPM包的统计信息:listacontentsummaryofanumberofRPMpackagesUSAGE:showrpmrpmfile1rpmfile2.EXAMPLE:showrpm/cdrom/Red

45、Hat/RPMS/*.rpmforrpmpackagein$*;doif-r$rpmpackage;thenecho=$rpmpackage=rpm-qi-p$rpmpackageelseechoERROR:cannotreadfile$rpmpackagefidone如果您运行如果您运行showrpmopenssh.rpmw3m.rpmwebgrep.rpm此时$*包含了3个字符串,即openssh.rpm,w3m.rpmandwebgrep.rpm.5.引号在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符(比如jpg件,*)替换成合适的文件名,它变量替换

46、成变量值。为了防止程序作这种替换,您可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件,两个mail.jpg和tux.jpg。1.2编译SHELL脚本#ch#!/bin/shmod+xfilenamecho*.jpgU缓螅梢酝D淙耄?./filename来执行您的脚本。这将打印出mail.jpgtux.jpg的结果。引号(单引号和双引号)将防止这种通配符扩展:#!/bin/shecho*.jpgecho*.jpg这将打印*.jpg两次。单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。#!/bin/shecho$SHELLecho$SHELLecho$

47、SHELL运行结果为:/bin/bash/bin/bash$SHELL最后,还有一种防止这种扩展的方法,那就是使用转义字符反斜杆:echo*.jpgecho$SHELL这将输出:*.jpg$SHELL6.Heredocuments当要将几行文字传递给一个命令时,heredocuments译者注:目前还没有见到过对该词适合的翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个heredocuments就不必用echo函数一行行输出。一个Heredocument以开头,后面接上一个字符串,这个字符串还必须出现在heredocument的末尾。下面是一个例子,在该例子中

48、,我们对多个文件进行重命名,并且使用heredocuments打印帮助:#!/bin/sh#wehavelessthan3arguments.Printthehelptext:if$#-lt3;thencatren-renamesanumberoffilesusingsedregularexpressionsUSAGE:renregexpreplacementfiles.EXAMPLE:renameallrenHTM$html*.HTMfilesin*.html:*.HTMHELPexit0fiOLD=$1NEW=$2#Theshiftcommandremovesoneargumentfrom

49、thelistof#commandlinearguments.shiftshift#$*containsnowallthefiles:forfilein$*;doif-f$file;thennewfile二echo$file|seds/$0LD/$NEW/gif-f$newfile;thenechoERROR:$newfileexistsalreadyelseechorenaming$fileto$newfile.mv$file$newfilefifi您就会发现在程序中可能在几个地方使用了相同的代done字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出。如果输入参数

50、等于或大于3个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。下一步,我们使用shift命令将第一个和第二个参数从参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。接着我们判断该文件是否存在,如果存在则通过sed命令搜索和替换这是一个复杂一些的例子。让我们详细讨论一下。第一个辻表达式判断输入命令行参数是否小于3个(特殊变量$#表示包含参数的个数)。如果输入参数小于3个,则将帮助文来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目的:得到了旧文件名和新文

51、件名。然后使用4)函数如果您写了一些稍微复杂一些的程序,mv命令进行重命名。码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:functionname()insidethebody$1isthefirstargumentgiventothefunction$2thesecond.body您需要在每个程序的开始对函数进行声明。下面是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称。这里使用了一个叫做help的函数。正如您可以看到的那样,这个定义的函数被使用了两次。#!/bin/sh#vim:setsw=4ts=4et:help()catxtitleb

52、ar-changethenameofanxterm,gnome-terminalorkdekonsoleUSAGE:xtitlebar-hstring_for_titelbarOPTIONS:-hhelptextEXAMPLE:xtitlebarcvsHELPexit0#incaseoferrororif-hisgivenwecallthefunctionhelp:-z$1&help$1=-h&help#sendtheescapesequencetochangethextermtitelbar:echo-e330;$107#在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理

53、解脚本。命令行参数我们已经见过$*和$1,$2.$9等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值(比如文件名)。有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无遗是一个不错的方法。#!/bin/shhelp()catshiftby2-)shift;break;#endofoptions-*)echoerror:nosuchoption$1.-hforhelp;exit1;*)break;esacdoneechoopt_fis$opt_fechoopt_lis$opt_lechofirstargis$1echo2ndargis$2您可以这样运行该脚本:cmdparser-lhello-f-somefile1somefile2返回的结果是:opt_fis1opt_lishellofirstargis-somefile1将输入参数与Unix系统的惯例,并copy命令:expr命令2ndargissomefile2这个脚本是如何工作的呢?脚本首先在所有输

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论