Linux 正则表达式详解
之前有写过两篇关于sed、awk的文章,但是内容太过简单了。近期打算就这方面话题写系列,系统介绍一些与shell script有关的内容。因 为即将介绍的一系列内容都将与正则表达式有关联,所以作为这个系列的开篇之作,先详细介绍一下正则表达式的使用。关于正则表达式的文章相信已经数不胜数 了,我之所以再写一篇,一方面结合自己学习的心得用自己的话来组织一下,希望对刚接触正则的朋友有所帮助;另一方面也是自己再做个总结写个笔记加深理解。进入正题吧。首先要解决的一系列问题是:正则是什么,哪些场合用到正则,正则能解决什么问题?(注:我下面要给出的一系列定义都未必是各大书籍的经典定义,而是我自己理解自己组织的语言)正则表达式描述了特殊的字符序列,也就是,正则表达式的结果就是一系列字符,不论它有多复杂或是多简单。我们接下来要讨论的正则表达式(或称Regular Expression,简称RE)都是指linux/unix系统中grep、ed、sed工具中所使用的RE(使用RE的并非只有这些工具,例如php、perl都使用RE,但是他们不在我们讨论的范围之内)。为什么不提egrep和awk呢?因为他们使用的RE和grep、sed所使用的有些很小的区别,他们将在本文的后半部分提到。还是举点例子吧,晦涩的文字太不直观了!我们下面的大多数例子都将以grep工具来讲,因为grep是linux/unix系统最常用最简单而且要使用RE的工具!既然要拿grep来举例,还是先介绍一下grep吧。grep命令的作用是在一个或多个文件中搜索特定的字符串,语法为:grep pattern file(s)每个文件中符合模式pattern的字符串所在的行都将显示在终端上。(注意,这里的pattern将广泛使用在grep、sed、awk中,事实上RE就是使用在pattern中的!)最简单的一个例子:grep ‘root’ /etc/passwd上面这个grep命令中,root就是一个最简单的RE!整条命令的意思就是:在文件/etc/passwd中搜索包含字符串root的行,并把它(们)显示出来。(这里的单引号’’要讨论起来过于复杂,我们将在其他的文章中重点讨论,记得先这么用吧grep ‘xxxx’ file)为什么root也是一个RE呢?别把RE看得过于复杂,在不使用特殊字符(在RE中称为元字符)的情况下,RE就是一个一个的字符而已!记住: RE都只是处理单个字符的!root这个pattern到底是怎么工作的呢?很简单,就是在每一行先找r字符,如果找到了,再依次找oot。换句话说,就是要找到r后面紧跟着o再紧跟着o再紧跟着t的,才把该行显示出来。再复杂的RE也都是这样工作的!那RE岂不是很简单?它难在哪里呢?难就难在它最强大的地方,模糊匹配,也就是下面要讲的元字符。(如果没有元字符,都像’root’这样,也就没必要搞什么RE了,pattern里写个单词不就得了)重点难点的元字符来了啊!很多书和文章都会一鼓脑儿把元字符列一张表,让学习者去理解或者背下来。这样的效果是,那张表不结合实例看三遍以上是理解不了的!结合我以前学习的心得,我把元字符分成2类来介绍。其实元字符总共也没几个,分类是为了便于理解。第一类:可以单独使用的元字符。这类字符有(下面列出来的字符都请一个一个的看,不要连起来,因为他们都是独立存在就有意义的). ^ $.代表任意单个字符^作为RE的第一个字符,代表行的开始;在其他位置是普通字符$作为RE的最后一个字符,代表行的结束;在其他位置是普通字符举例: $cat file11111.12222^23333$3 注意这是一个空行$grep ‘.’ file11111.12222^23333$3为什么会显示三行呢?因为命令中的.是元字符,而不是普通的点。元字符.代表任何单个字符,所以只要有字符的行,这条grep命令都会把它显示出来。$grep ‘^’ file11111.12222^23333$3 注意这里的空行也显示了为什么没有^符号的行也显示呢?因为这个RE中^是在第一个字符位置,这里的^代表行首,只要有行首的行都显示(任何行哪怕是空行都有行首和行尾)同样的道理grep ‘$’ file也会显示所有行。$grep ‘.^’ file2222^2这个命令中的^前面有个元字符,所以这里的^不表示行首,而是个普通字符;.^表示一个任意字符后面紧跟字符^,这里匹配的内容就是2^,于是这一行被显示。$grep ‘$.’ file3333$3这个命令中的$后面有一个元字符,所以不表示行尾,$.匹配的是$3,于是该行被显示。$grep ‘^$’ file 这里显示了一个空行^$匹配行首和行尾之间没有字符的行,也即是空行了。^$表示空行,而^ $(中间有个空格哦)表示只有一个空格的行。好了,第一类元字符介绍完了,简单吧,只有三个而已。第二类,用来修饰其他字符(普通字符或第一类元字符)的元字符,这一类元字符要多一些,一个一个来吧。常用的匹配单个字符的还有[],[…]匹配括号中的字符之一。下面列举一些常见的使用方式:[abc] 匹配单个字符a或b或c[123] 匹配单个字符1或2或3[a-z] 匹配小写字母a-z之一[a-zA-Z] 匹配任意英文字母之一[0-9a-zA-Z]匹配任意英文字母或数字之一注意上面标红色的单个和之一了吧,不管[]里面多复杂,它的结果都是一个字符!在[]里面的字符值得注意的有几个特例:- ^ [ ] (也请分开一个一个看)-在上面的例子已经提到了,表示范围。但是注意:如果-符号出现在[]里面的首尾位置是普通字符。例如:[-abc-] 匹配字符-abc之一 -符号虽然出现了2次,这里和一个-是同样的意义,试想aa之一和aaa之一有区别吗?^符号如果出现在[]的起始位置表示否定,但是在其他位置是普通字符。[^ab^c] 匹配不是a或b或^或c的任意字符$cat fileAaaaabcBbbbbbc^cccccbc33$grep ‘[^ab^c]’ filecccccbc33只有第三行的3满足了匹配要求,所以只显示这一行。$grep ‘[x^]’ fileBbbbbbc^[x^]匹配字符x或^如果[]中要包含字符[和]该怎么办呢,[][]应该怎么理解呢?[[]]又怎么理解呢?有一个原则:字符]和[放在[]中,只有紧跟在[后面的]和紧贴于]前面的[是普通字符。还有一个更好理解的方式,就是用反斜杠转义[]中的[和],如[\[\]],当然这看起来同样不那么舒服。除了[]之外,还有很多第二类元字符,先来整体认识一下他们吧(这次不是一个一个看了,以空格为分界来分段看吧)* \ \? \+ \{n,m\}* 用于修饰前导字符,表示前导字符出现任意多次\? 用于修饰前导字符,表示前导字符出现0或1次\+ 用于修饰前导字符,表示前导字符出现1或多次\{n,m\} 用于修饰前导字符,表示前导字符出现n至m次 (n和m都是整数,且n<m)\ 用于转义紧跟其后的单个特殊字符,使该特殊字符成为普通字符注:以上“前导字符”表示紧贴于元字符前面的单个普通字符或第一类元字符。举例吧:a* 匹配连续的任意(也包括0)个a.* 匹配连续的任意(也包括0)个任意字符,传说中的万能匹配!a\? 匹配0或1个aa\+ 匹配1或多个aa\{3,5\} 匹配3至5个连续的a\.* 匹配0或多个连续的. \.表示普通字符句点.注意到没有,* \? \+ \{n,m\}这几种元字符完成类似的功能,都是匹配连续出现的前导字符,只是出现的次数不一样罢了,不是很难吧。\{n,m\}还有其他几种形式:\{n\} 连续的n个前导字符\{n,\} 连续的至少n个前导字符发现没有,\?等价于\{0,1\} *等价于\{0,\} \+等价于\{1,\}特别提一下,你可能会在很多地方看到?和+,而不是这里说的\?和\+。这个问题我在开篇有所提及。grep/sed用的是\?和\+,普通正则RE;egrep/awk用的是?和+,扩展正则ERE。仅这点区别而已,RE和ERE大部分是相同的。还有一组元字符也是常用的,但是相对比较难理解,拿到这里单独说一下:\( \)这里的\(和\)一定是成对出现的,这对带反斜杠的小括号的意义是:将小括号中匹配的字符串存储到下一个寄存器中(1-9)。\( \)在sed的s///替换中经常使用,其实它并不限于应用在sed中,举例:^\(.\) 行中第一个字符存到1号寄存器中(为什么是行中第一个字符?回上面复习一下吧^\(.\)\1行首两个字符,且他们相同^\(.\).*\1$ 行首尾两个字符相同\1的意思就是取1号寄存器的内容,这是固定格式\n(1≤n≤9)$cat fileaaaaabcbc^b1234gdfdd$ grep '^\(.\)\1' fileaaaabc$ grep '^\(.\).*\1$' filebc^b正则表达式理论方面的就介绍到这里了,下面再补充一些更常用也更长一点的RE例子。[0-9a-z?,.;:’”]这个表达式将匹配“任意单个字符,可以是数字、小写字母、问好、逗号、句号、分号、冒号、单引号或双引号[0-9]\{2\} 连续的两位数字[0-1][0-9][-/][0-3][0-9][-/][0-9]\{2\}这个表达式能够用来表示时间格式MM-DD-YY或MM/DD/YY,方括号[]中的-放在第一个位置,确保它在[]中不被解释为范围,而是普通字符-还有一点要注意的,就是\{2\}仅是用来修饰前面的单个字符的,别忘了[0-9]也是单个字符gep ‘<.*>’ file 将匹配所有带有<>标记的行can[ no’]*t 将匹配cant、can t、cannt、cannot、cann’t、cannnnnnt等等。。。80[234]\ ?86将匹配8086、80286、80386、80486^$ 匹配空行^.*$和.*都匹配任意行(包括空行)[0-9][0-9]*\.\{5,\}[0-9][0-9]*匹配“至少一位数字紧跟至少5个句点紧跟至少一位数字。这个正则应该分段来看:[0-9]是一位数字;[0-9]*是0或多位数字;[0-9][0-9]*就是“至少一位数字”,相当于[0-9]\+\.\{5,\}中的.被转义了,表示普通的. 于是\.\{5,\}就表示”至少5个句点”先举这些例子吧,更多的例子以后再更新了
顶(0)
踩(0)
下一篇:shell学习笔记一--总括
- 最新评论