1、第三章 Shell编程本章概要什么是Shell脚本正则表达式与grep命令用Bash Shell编程什么是Shell脚本?一个shell脚本程序(shell script)是包含Linux命令的文本文件。我们可以使用任何标准编辑器输入Linux命令。例如vi、emacs、WordPerfect,以及任何GNOME或KDE的文本编辑器。3.1 Shell编程概述一个Shell脚本就是一组Shell的命令和语句,把它们放在一个文件里。可以交互式地运行这些脚本,也可以计划在未来的某个时间里自动地或无人监管地运行某个脚本。举一个例子。DOS在文本文件每一行的结尾都有一个换行符和一个回车作为标记;Lin
2、ux(其他UNIX系统也是一样)在每一行的最后只使用一个换行符。如果我们使用带有-b选项的vi编辑器打开一个DOS文件,将看到在每一行在最后都有一个M符号。这个M代表ctrl+M,它表示的是回车符。在Linux系统上,通过使用带-d-d选项的选项的trtr命令命令可以很容易地将DOS文本文件中的那些额外的回车符去掉。为什么要建立Shell程序呢tr命令字符翻译tr用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作
3、开始。大小写转换。去除控制字符。删除空行。tr命令格式troptiontroption string1string2string1string2字符串string1中的输入字符映射到string2中的对应字符。各选项的含义如下:-c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。-d 删除字符串1中所有输入字符。-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。注意:指定字符串1或字符串2的内容时,只能使用单字符或字符串范围或列表。举例说明tr的用法:tr“a-z”“A-Z”/etc/passwdtr“a-z”“A-Z”/etc/passwd把/
4、etc/passwd文件输出到屏幕上,并把所有的小写字母变成大写字母。tr “a-z”“b-za”/.bashrctr “a-z”“b-za”/.bashrc把.bashrc输出到屏幕上,但是字符是经过循环处理的。我们将一个名filename.dos的DOS文本文件转换为名为filename.linux的Linux文本文件。可以输入下面的命令:$t r d “0 1 5 ”f i l e n a m e.d o s$t r d “0 1 5 ”filename.linuxfilename.linux 注:015是用八进制数表示的回车符的ASCII码。同许多UNIX程序一样,tr的读写操作都是针
5、对标准输入和标准输出的设备,所以我们在此必须使用I/O的重定向,才能利用tr删除一个文件中所有指定字符,并将输出存入另一个文件中。我们可以把下面这行存储到一个名为dos2linuxdos2linux的文件中:trtr d“015”$2 d“015”$2(注:Bash有一些专门存储命令行参数的变量。在一个Shell脚本中,$0表示该Shell脚本的名字;变量$1、$2等表示命令行参数。)类比:在C程序中main函数参数表中的参数 main(int argc,char*argv)然后,通过使用下面的命令将其做成可执行文件:$chmod$chmod+x dos2linux+x dos2linux假如
6、我们有一个挂装为/dosc的MS-DOS分区,可以试用一下dos2linux这个Shell程序:$dos2linux/dosc/autoexec.bat aexec.bat$dos2linux/dosc/autoexec.bat aexec.bat 编写脚本和编写程序有什么不同脚本和程序之间的区别是,脚本是一个文本文件。在该文件里写命令并执行文件无需中间步骤。反之,程序要运行必须对程序的源代码进行编译。由编译器生成计算机能够读懂的可执行机器代码。Shell支持大多数编程语言结构,比如:变量和数组参数传递逻辑和流程结构(ifthenelse块、与、或、非)case 语句循环结构(until、wh
7、ile、for)函数(内部及用户定义的)注释脚本的文档系统编程语言“从头开始”设计数据结构和算法,从最基本的内存单元开始设计;脚本语言则是在现有的多功能库基础上实现新功能。系统编程语言是强类型语言,有助于处理复杂的问题;而脚本语言则一般不使用类型,用于简化元件之间的关系,可以快速开发。系统编程语言和脚本语言系统编程语言的历史 系统编程语言先是作为汇编语言的替代品。汇编语言反映机器的每一个层面,每一条语句代表单一的机器指令。程序设计者要做很低级的事情,诸如调用寄存器、处理杂事等。因此,用汇编语言编写及维护大型程序,是相当困难的。50年代晚期,高级语言如Lisp、FORTRAN和Algol出现了。
8、程序员不再需要直接编写机器指令了,由编译器来负责把高级语言程序的源代码编译成可执行码。随着时间的推移,一系列的程序设计语言从Algol衍生出来,包括PL/1、Pascal、C、C+以及Java。平均每行高级语言大约能编译成5行汇编语言。系统编程语言的显著特点是具有“类型”。类型是指信息的意义被事先指定的程度。如C语言中定义int a;表示a这个变量被当作int使用,这就构成了C类型的一部分。现代计算机系统基本上没有类型,内存单元可以存放任何值:整数、浮点数、指针或者指令等等。一个值的意义决定于它如何被使用。如果程序指针指向内存的某个单元,那该单元就被当作指令;如果一个单元被一个加法指令调用,那
9、它就被当作整数。强类型语言目前所有系统编程语言都是强类型的。每个变量都有类型,用法也须遵循该类型;数据段与代码段完全分开,在线产生新代码相当困难;变量可以放到结构或对象里面,该用A类型对象时就不能用B类型对象。类型的优点 首先,类型把东西的用途都说明清楚,又限定不同的东西要以不同的方式对待,因此大型程序就比较容易管理。第二,编译器能由类型的信息产生最优化编码;如果编译器事先知道一个东西被作为整数来用,那么当它被拿来做加法时,编译器可以产生整数加法的指令。如果不知道的话,就要在执行时期检测,这样做的代价比较高昂。第三,编译器能由类型的信息来找出特定种类的错误。例如,把一个浮点数当作指针来用。脚本
10、语言脚本语言可以用来扩展已经存在元件的功能,而很少用来开发复杂的数据结构和算法,这些应该由元件提供。因此,脚本语言被称为连接语言(Glue L a n g u a g e)或 者 系 统 集 成 语 言(S y s t e m Intergration Language)。为了简化联结元件的工作,脚本语言通常没有类型。脚本语言通常是字符串导向。因为这能对许多类型的变量提供单一的表示方法。脚本语言比系统语言更高级。脚本语言一般有一组元件已经用别的语言(一般为C语言)写成。脚本语言不会从头开始,而是组合已经写好的元件。如Tcl和VB可以用来管理GUI元件,而UNIX Shell可以把元件当作过滤器
11、来组成一条“流水生产线”,最终产生所要的结果。无类型的语言更容易结合元件,因为它并不对东西该如何使用做任何限制,而强类型语言不利程序代码的再利用。为了适应不同类型的数据,就得设计许多不同的表达方法。脚本语言的效率一般比系统编程语言差。脚本语言比系统语言更高级,一行脚本语言相当于数百或数千行汇编语言,而一行系统编程语言只相当于5行。综上所述,脚本语言用来开发应用程序的优点是开发速度快和易用性;而系统编程语言的优点在于其能够实现复杂的功能、算法以及运行时的速度。Shell提供了一套完整的字符串模式匹配规则,或者称之为元字符,这样就可以按照所要求的模式来匹配文件。匹配文件名中的任何字符串。匹配文件名
12、中的单个字符。匹配文件名中的字母或数字字符。这些字符有*、?、.等,当shell遇到上述字符时,就会把它们当作特殊字符,而不是文件名中的普通字符,这样用户就可以用它们来匹配相应的文件名。3.2 shell中的元字符shell中的特殊字符 通配符 通配符用于模式匹配,如文件名匹配、路经名搜索、字符串查找等。常用的通配符有*、?和括在方括号 中的字符序列。*代表任何字符串(长度可以不等),例如:“f*”匹配以f打头的任意字符串。但应注意,文件名前的圆点(.)和路经名中的斜线(/)必须显式匹配。例如“*”不能匹配.file,而“.*”才可以匹配.file。shell中的特殊字符?代表任何单个字符。代
13、表指定的一个字符范围,只要文件名中 位置处的字符在 中指定的范围之内,那么这个文件名就与这个模式串匹配。方括号中的字符范围可以由直接给出的字符组成,也可以由表示限定范围的起始字符、终止字符及中间的连字符(-)组成。表通配符含义举例 模式串 意 义*当前目录下所有文件的名称。*Text*当前目录下所有文件名中包含有Text的文件的名称。ab-dm*当前目录下所有以a、b、c、d、m开头的文件的名称。ab-dm?当前目录下所有以a、b、c、d、m开头且后面只跟有一个字符的文件的名称。/usr/bin/?目录/usr/bin下所有名称为两个字符的文件的名称。特别需要注意的是:连字符“-”仅在方括号内
14、有效,表示字符范围,如在方括号外面就成为普通字符。*和?只在方括号外面是通配符,若出现在方括号之内,它们也失去通配符的能力,成为普通字符了。例如,模式“-a*?abc”中只有一对方括号是通配符,*和?均为普通字符,因此,它匹配的字符串只能是-a*abc和-a?abc。例子:为了列出所有以大写字母开头的文件名,可以用:$ls A-Z*为了列出所有以小写字母开头的文件名,可以用:$ls a-z*为了列出所有以数字开头的文件名,可以用:$ls 0-9*为了列出所有以.开头的文件名(隐含文件,例如.profile、.rhosts、.history等等),可以用:$ls.*由于*、?和 对于shell来
15、说具有比较特殊的意义,在正常的文件名中不应出现这些字符;特别是在目录名中不要出现它们。否则Shell匹配起来可能会无穷的递归下去。使用通配符时需要注意的问题引用 脚本中执行行操作时,shell将对脚本设置予以解释。例如:表 shell引用类型“”双引号 反引号 单引号 反斜线 需要引用的特殊元字符;命令分隔符&后台处理()命令编组:创建子shell 命令编组:不创建子shell|管道 输出重定向newline 命令终止space/tab 词分隔符$变量替换字符*?用于文件名展开的shell元字符shell中的引号 在shell中引号分为三种:单引号,双引号和反引号。单引号 由单引号括起来的字符
16、都作为普通字符出现。特殊字符用单引号括起来以后,也会失去原有意义,而只作为普通字符解释。例如:$string=$PATH$echo$string$PATH$可见$保持了其本身的含义,作为普通字符出现。双引号“由双引号括起来的字符,除$、和“这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。对于$来说,就是用其后指定的变量的值来代替这个变量和$;对于而言,是转义字符,它告诉shell不要对其后面的那个字符进行特殊处理,只当作普通字符即可。这样,在双引号中需要在前面加上的只有四个字符$,和”本身。而对”号,若其前面没有加,则Shell会将它同前一个”号匹配。例如,我们假定PAT
17、H的值为.:/usr/bin:/bin,输入如下命令:$TestString”$PATH”$PATH”$echo$TestString.:/usr/bin:/bin”$PATH$反引号 反引号()这个字符所对应的键一般位于键盘的左上角,不要将其同单引号()混淆。反引号括起来的字符串被shell解释为命令行。在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分。反引号 例如:$pwd/home/xyz$string=”current directory is pwd”$echo$string current directour is/home/xyz$利
18、用反引号的这种功能可以进行命令置换,即把反引号括起来的执行结果赋值给指定变量。例如:$today=date$echo Today is$today Today is Mon Apr 15 16:20:13 CST 2009$反引号还可以嵌套使用。但需注意,嵌套使用时内层的反引号必须用反斜线()将其转义。例如:$abc=echo The number of users is who|wc-l$echo$abc The number of users is 5$命令替换 命令替换和重定向有些相似,但区别在于命令替换是将一个命令的输出作为另外一个命令的参数。常用命令格式为:command1 comm
19、and2 其中,command2的输出将作为command1的参数。需要注意的是这里的符号,被它括起来的内容将作为命令执行,执行后的结果作为command1的参数。例如:$cd pwd 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下。反斜线如果下一个字符有特殊含义,反斜线防止shell误解其含义,即屏蔽其特殊含义。下述字符包含有特殊意义:&*+$“|?。假定echo命令加*,意即以串行顺序打印当前整个目录列表,而不是一个星号*。为屏蔽星号特定含义,可使用反斜线。上述语句同样可用于$命令,s h e l l解释其为现在进程I D号,使用反斜线屏蔽此意,仅打印$。注释符
20、 在shell编程中经常要对某些正文行进行注释,以增加程序的可读性。在Shell中以字符“#”开头的正文行表示注释行。3.3 正则表达式与grep命令3.3.1 正则表达式 3.3.2 grep的使用 UNIX的文本处理工具UNIX工具很丰富,如ls、pwd、who、vi和sort等等。其中有三个是UNIX上最重要的文本处理工具:grep、sed和awk。这些工具用于处理来自管道或标准输出的文本。实际上,sed和awk本身常被用做脚本语言。而要使用grep、sed和awk的强大功能,就必须先学会使用正则表达式和正则表达式元字符。当从一个文件或命令输出中抽取或过滤文本时,可以使用正则表达式。什么
21、是正则表达式(RE)?正则表达式是一种字符模式,用于在查找过程中匹配相同的字符。它由一些特殊元字符和普通的字符组成。3.3.1 正则表达式 在大多数程序里,正则表达式都被括在两个正斜杠(/)之间。例如:/love/就是一个正则表达式,在被查找的行中,模式love随时会被相同的模式匹配。为了抽取或获取信息,我们必须描述抽取操作应遵循的一些规则。这些规则由一些特殊字符或进行模式匹配操作时使用的元字符组成,也可以使用普通字符作为模式中的一部分进行搜索。例如A将查询A,x将查询字母x。Linux系统自带的所有大的文本过滤工具在某种模式下都支持正则表达式的使用。下面我们所介绍的基本元字符使用在:grep
22、(全局正则表达式版本,用于查找文件的内容)sed(流编辑,一种重要的文本过滤工具)命令中,AWK语言,结合(以字符出现的情况进行匹配的元字符)使用在AWK语言中。表 基本元字符集及其含义 元字符含义只匹配行首$只匹配行尾*一个单字符后紧跟*,匹配0个或多个此单字符 匹配内的字符,可以是一个单字符,也可以是字符序列,可以使用-表示中字符序列范围 用来屏蔽一个元字符的特殊含义。因为在Shell中一些元字符有时有一些特殊含义,使之失去应有的含义.匹配任意单字符patternn用来匹配前面pattern出现次数。n为次数patternn,m含义同上,但pattern出现次数在n和m之间1使用句点匹配单
23、字符 句点“.”可以匹配任意单字符。例如,如果要匹配一个字符串,以beg开头,中间夹一个任意字符,那么可以表示为 beg.nbeg.n。在ls-l命令中,可以匹配一定权限:.x.x.x.x.x.x 此格式匹配用户本身、用户组及其他用户的执行权限。drwxrwxrwdrwxrwxrw-no matchno match-rw-rw-rw-rw-rw-rw-no matchno match-rwxrwxr-x-rwxrwxr-x match match-rwxr-xr-x-rwxr-xr-x match match 假定正在过滤一个文本文件,对于一个有10个字符的脚本集,要求前4个字符之后为xc,后
24、4个字符为任意。匹配操作如下:.xc.xc.按下例运行:1234xc9088 1234xc9088 match match4523xx9001 4523xx9001 no match no match0011xA9912 0011xA9912 no match no match9931xc3455 9931xc3455 match match注意:句点“.”允许匹配ASCII集中任意字符,或为字母,或为数字。2在行首以匹配字符串或字符序列 只允许在一行的开始匹配字符或单词。例如使用ls-l命令,并匹配目录。dddrwxrwxrwdrwxrwxrw-match match-rw-rw-rw-rw
25、-rw-rw-no match no matchdrwxrwxr-xdrwxrwxr-x match match-rwxr-xr-x-rwxr-xr-x no match no match 回到上个脚本,使用001001,结果将匹配每行开始为001的字符串或单词:1234xc9088 1234xc9088 no match no match4523xx9001 4523xx9001 no match no match0011xA9912 0011xA9912 match match9931xc3455 9931xc3455 no match no match 可以将各种模式结合使用,例如:4x
26、c4xc.结果为:1234xc9088 1234xc9088 match match4523xx9001 4523xx9001 no match no match0011xA9912 0011xA9912 no match no match9931xc3455 9931xc3455 no match no match3224xc193 3224xc193 no match no match在正则表达式中使用频繁,因为大量的抽取操作通常在行首。3在行尾以$匹配字符串或字符$与正相反,它在行尾匹配字符串或字符。$符号放在匹配单词之后。例如:要匹配每行以ld结尾的所有字符串。操作为ld$ld$如果要
27、匹配所有的空行,执行以下操作$如果只返回包含一个字符的行,操作如下:.$.$如果在行尾匹配单词jet01,操作为jet01$jet01$4使用*匹配字符串中的单字符或其重复序列使用*匹配任意字符或字符串的重复多次表达式。例如:compucompu*t t将匹配字符u一次或多次:computercomputingcompuuuuuute 1013310133*匹配:10133310133101333344445使用屏蔽一个特殊字符的含义 什么是特殊字符?一般意义上,下列字符可以认为是特殊字符:$.“$.“*!()+?!()+?假定要匹配包含字符“.”的各行,而“.”代表匹配任意单字符的特殊字符,
28、因此需要屏蔽其含义。操作如下:.(上述模式不认为反斜杠后面的字符是特殊字符,而是一个普通字符,即句点.)6使用 匹配一个范围或集合 使用 匹配特定字符串或字符串集,可以用逗号将括号内要匹配的不同字符串分开.使用“-”表示一个字符的范围。假定要匹配任意一个数字,可以使用01234567890123456789,更可以简化为0-90-9。假定要匹配任意字母,则使用A-Za-zA-Za-z 假定要匹配一个单词,以s开头,中间有一任意字母,以t结尾,则使用:sa-z A-Ztsa-z A-Zt 要匹配computer或Computer两个单词,可做如下操作:Cc omputerCc omputer要匹
29、配所有包含system后跟句点的所有单词,这里s可以大写或小写。使用如下操作:S,systemS,system.结合*与更有效益。例如a-z A-Za-z A-Z*将匹配所有的单词。注意符号的使用,当直接用在一个括号里,意指否定或不匹配括号里的内容。a-z A-Za-z A-Z 匹配任一非字母型字符0-90-9 匹配任一非数字型字符 7使用匹配模式结果出现的次数 模式有三种形式,即:patternn 匹配模式出现n次 patternn,匹配模式出现最少n次patternn,m 匹配模式出现n到m次之间,n、m为0255中任意整数。请看例子。匹配字母A出现2次,并以B结尾。操作如下:A2BA2B
30、 (AAB)匹配字母A出现至少4次,使用:A4A4,BB (AAAAB,AAAAAAAB,但不能为AAAB)假定从下面列表中抽取代码.格式如下:前4个字符是数字,接下来是xx,最后4个也是数字。0-94xx0-940-94xx0-94结果:1234xc9088 1234xc9088 no matchno match4523xx9001 4523xx9001 matchmatch0011xA9912 0011xA9912 no matchno match9931xc3455 9931xc3455 no matchno match总结在写正则表达式时,有点难度或达不到预期效果,可以:(1)在写正则
31、表达式前先写下预期的输出结果。(2)可以记住一些基本模式。grep有三种变形:grep命令:一次只能搜索一个指定的模式;egrep命令:检索扩展的正则表达式(包括表达式组和可选项);fgrep命令:检索固定字符串,它不识别正则表达式,是快速搜索命令。4.3.2 grep的使用 语法这组命令在指定的输入文件中查找与模式匹配的行。如果没有指定文件,则从标准输入中读取。正常情况下,每个匹配的行被显示到标准输出。如果要查找的文件是多个,则在每一行输出之前加上文件名。语法:grepgrep 选项选项 查找模式查找模式 文件名文件名1 1,文件名,文件名2 2,egrepegrep 选项选项 查找模式查找
32、模式 文件名文件名1 1,fgrepfgrep 选项选项 查找模式查找模式 文件名文件名1 1,1.grepgrep的一般形式:grepgrep 选项选项 基本正则表达式基本正则表达式 文件文件 注:基本正则表达式可为字符串。双引号引用在grep命令中输入字符串参数时,最好使用双引号括起来。例如:“my string”“jet plane”my string”“jet plane”这样做有两个原因:是以防被误解为Shell命令;可以用来查找多个单词组成的字符串。在使用变量时也应该使用双引号;在使用模式匹配时,应使用单引号。注:由单引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后,
33、也会失去原有意义,而只作为普通字符解释。由双引号括起来的字符,除$、和”这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。grep选项常用的选项有:-c-c 只显示匹配行的数量。-i-i 比较时不区分大小写,只适用于单字符。-h-h 在查找多个文件时,指示grep不要将文件名加入到输出之前。-n-n 在输出前加上匹配串所在行的行号(文件首行行号为1)。-v-v 只显示不包含匹配串的行。grep可以查询多个文件。例如:在当前目录下所有的.doc文件中查询字符串“sort”。方法如下:$grepgrep “sort”“sort”*.doc.docdata.f的记录结构$cat
34、data.fcat data.f48 Dec 3BC1997 LPSX 68.00 LVX2A 13848 Dec 3BC1997 LPSX 68.00 LVX2A 138483 Sept 5AP1996 USP 65.00 LVX2C 189483 Sept 5AP1996 USP 65.00 LVX2C 18947 Oct 3ZL1998 LPSX 43.00 KVM9D 51247 Oct 3ZL1998 LPSX 43.00 KVM9D 512219 dec219 dec 2cc1999 CAD 23.00 PLV2C 68 2cc1999 CAD 23.00 PLV2C 68484
35、nov484 nov 7PL1996 CAD 49.00 PLV2C 234 7PL1996 CAD 49.00 PLV2C 234483 may 5PA1998 USP 37.00 KVM9D 644483 may 5PA1998 USP 37.00 KVM9D 644216 Sept 3ZL1998 USP 86.00 KVM9E 234216 Sept 3ZL1998 USP 86.00 KVM9E 234城市位置编号月份存储代码及出库年份产品代号产品统一标价标识号合格数量行匹配$grepgrep c“48”data.f c“48”data.f$4 4 要显示包含“48”的字符串的4行文
36、本:$grepgrep “48”data.f “48”data.f48 Dec 3BC1997 LPSX 68.00 LVX2A 13848 Dec 3BC1997 LPSX 68.00 LVX2A 138483 Sept 5AP1996 USP 65.00 LVX2C 189483 Sept 5AP1996 USP 65.00 LVX2C 189484 nov484 nov 7PL1996 CAD 49.00 PLV2C 234 7PL1996 CAD 49.00 PLV2C 234483 may 5PA1998 USP 37.00 KVM9D 644 483 may 5PA1998 USP
37、 37.00 KVM9D 644 行数显示满足匹配模式的所有行行数:$grepgrep n “48”data.f n “48”data.f 1 1:48 Dec 3BC1997 LPSX 68.00 LVX2A 13848 Dec 3BC1997 LPSX 68.00 LVX2A 1382 2:483 Sept 5AP1996 USP 65.00 LVX2C 189483 Sept 5AP1996 USP 65.00 LVX2C 1895 5:484 nov484 nov 7PL1996 CAD 49.00 PLV2C 234 7PL1996 CAD 49.00 PLV2C 2346 6:48
38、3 may 5PA1998 USP 37.00 KVM9D 644483 may 5PA1998 USP 37.00 KVM9D 644 显示非匹配行显示所有不包含“48”的各行。$grepgrep v “48”data.f v “48”data.f47 Oct 3ZL1998 LPSX 43.00 KVM9D 51247 Oct 3ZL1998 LPSX 43.00 KVM9D 512219 dec219 dec 2cc1999 CAD 23.00 PLV2C 68 2cc1999 CAD 23.00 PLV2C 68216 Sept 3ZL1998 USP 86.00 KVM9E 2342
39、16 Sept 3ZL1998 USP 86.00 KVM9E 234 精确匹配精确地抽取只包含“48”的各行。操作如下:$grep “48”data.f48 Dec 3BC1997 LPSX 68.00 LVX2A 13848 Dec 3BC1997 LPSX 68.00 LVX2A 138 另外一种方法是在抽取字符串后加上$grep “48”data.f 大小写敏感缺省的情况下,grep是大小写敏感的。要查询大小写不敏感字符串,必须使用-i开关。例如:$grep -i “septgrep -i “sept”data.f”data.f 2.grep和正则表达式 模式范围假如要抽取代码为“48
40、3”和“484”的城市,前面讲到可使用 来指定字符串范围。$grepgrep 4834 data.f 4834 data.f 不匹配行首如果要抽取记录,使其行首不是“48”,可以在 中使用记号。同时在方括号的前面也需要使用表示查询在行首开始。$grepgrep 48 data.f 48 data.f 设置大小写使用-i开关可以屏蔽月份sept的大小写敏感,也可以用另一种方式。可以使用 模式抽取各行包含sept和Sept的所有的信息。$grep Sseptgrep Ssept data.f data.f 如果要抽取包含Sept的所有行,无论大小写,并且此行包含字符串“483”,可以使用管道命令。
41、$grep Ssept data.f|grepgrep Ssept data.f|grep 483 483 匹配任意字符如果要抽取以L开头,以D结尾的所有代码。已知代码长度为5个字符:$grepgrep K.D data.f K.D data.f47 Oct 3ZL1998 LPSX 43.00 KVM9D 51247 Oct 3ZL1998 LPSX 43.00 KVM9D 512483 may 5PA1998 USP 37.00 KVM9D 644483 may 5PA1998 USP 37.00 KVM9D 644 日期查询例如:查询所有以5开头的1996或1998结尾的所有的记录。$g
42、repgrep 5.1996 5.1996,8 data.f8 data.f 查询空行$grep -n$myfilegrep -n$myfile使用-n参数显示实际行数。匹配特殊字符如果要查询文件名conftroll.conf。脚本如下:$grep conftroll.conf myfilegrep conftroll.conf myfile 查询格式化文件名使用正则表达式可匹配任意文件名。系统中对文本文件有其标准命名格式。一般最多6个小写字符,后跟句点,接着是两个大写字母。例如,在一个包含各类文件名的文件filename.deposit中定位这类文件名,方法如下:$g r e pg r e
43、p a-z 1,6 .A-Z 1,2 a-z 1,6 .A-Z 1,2 filename.depositfilename.deposit 3.系统grep命令 目录如果要查询目录列表中的目录。方法如下:$ls l|grepls l|grep d d如果在一个目录中查询不包含目录的所有的文件,方法如下:$ls l|grepls l|grep d d要查询其他用户和组成员有可执行权限的目录集合,方法如下:$ls l|grepls l|grep d.x.x d.x.x passwd文件$grep “Lynn”/etc/passwdgrep “Lynn”/etc/passwd查询/etc/passwd
44、文件中是否包含Lynn字符串。使用ps命令可使用ps ax命令的grep查询系统上运行的进程。例如我们要查看DNS服务器是否在运行(通常称为named)。方法如下:$ps ax|grepps ax|grep “named “named”小结grep是shell编程中很重要的工具。grep具有很强的灵活性,它是一个很强大而流行的工具。可在文件中快速查找字符串或模式。作业:grep练习 写出下面描述的grep命令,文本文件是file。1.打印包含词Tom的行2.打印包含Tom Savage的行3.打印以Tommy开头的行4.打印以.bak结尾的行5.打印至少包含一个大写字母的行6.打印这样一个模式的行,以大写字母开头,数字结尾,共有5个字符。7.打印包含Test或test的行。8.打印所有不包含Mary的行9.打印所有包含sam的行,sam的各种大小写形式都可以10.展开变量name的值,打印包含该值的所有的行