精通正则表达式笔记二---正则表达式基础概念?,+,*,{ },\,“ “,时间,小结

2 可选项元素

2.1 ?

现在来看color和colour的匹配。它们的区别在于,后面的单词比前面的多一个u,我们可以用colou?r来解决这个问题。元字符?(也就是问号)代表可选项。把它加在一个字符的后面,就表示此处容许出现这个字符,也可以不出现这个字符,问号前面的字符并非匹配成功的必要条件。
这个元字符与我们之前看到的元字符都不相同,它只作用于之前紧邻的元素。因此,colou?r的意思是:c,然后是o,然后是l,然后是o,然后是u,最后是r。u?是必然能够匹配成功的,有时它会匹配一个u,其他时候则不匹配任何字符。关键在于,无论u是否出现,匹配都是成功的。但这并不等于,任何包含?的正则表达式都永远能四配成功。例如,colo和u?都能在“semicolon”中匹配成功(前者匹配单词中的colo,后者什么字符都没有匹配)。可是最后的r无法匹配,因此,最终colou?r无法匹配semicolon。
另一个例子,我们需要匹配表示7月4日(July fourth)的文本,其中月份可能写作July或是Jul,而日期可能写作fourth、4th或者是4.显然,我们可以使用“(July|Jul)(fourth|4th|4),但也可以用其他的办法来解决这个问题。
首先,我们把(July|Jul)缩短为“(July?)。删除|之后,就没必要保留括号了。于是我们得到July? (fourth|4th|4)。然后,可以把4th|4简化为4(th)?。我们看到,现在作用的元素是整个括号了。括号内的表达式可以任意复杂,但是“从括号外来看”它们是个整体。界定作用对象是括号的主要用途之一。我们的表达式现在成了July? (fourth|4(th)?)
通过上面两个例子,可以看到正则表达式不是死板的教条,它更像是门艺术。

2.2 其他量词:重复出现

+(加号)和*(星号)的作用与问号类似。元字符+表示“之前紧邻的元素出现一次或多次”,而*表示“之前紧邻的元素出现任意多次,或者不出现”。换种说法就是,*表示“匹配尽可能多的次数,如果实在无法匹配,也不要紧”。+的意思是“匹配尽可能多的次数,但如果连一次匹配都无法完成,就报告失败“。问号、加号和星号这3个元字符,统称为量词,因为它们限定了所作用元素的匹配次数。
...?一样,正则表达式中的...* 也是永远不会匹配失败的,区别只在于它们的匹配结果。而...+在无法进行任何一次匹配时,会报告匹配失败。
在这里插入图片描述

2.3 规定重现次数的范围:区间

使用元字符序列来自定义重现次数的区间:(min,max)。这称为“区间量词(intervalquantifier)”。例如,{3,12}能够容许的重现次数在3到12之间。有人可能会用[a-zA-Z](1,5)来匹配美国的股票代码(1到5个字母)。问号对应的区间量词是{0.1}。

2.4 括号及反向引用

前面已经见过括号的两种用途:限制多选项的范围;将若干字符组合为一个单元,受问号或星号之类量词的作用。现在介绍括号的另一种用途:括号能够移“记住”它们包含的子表达式匹配的文本。在解决单词重复问题时会用到这个功能。
查找重复单词,比如在一行中有连续的“the the”两个重复的单词,我们先匹配第一个单词,接下来检查“后面的单词是否与它一样”。如果你的egrep支持“反向引用(backreference)”,就可以这么做。反向引用是正则表达式的特性之一,它容许我们匹配与表达式先前部分匹配的同样的文本。
我们先把’the the“中的第一个the替换为能够匹配任意单词的正则表达式[A-Za-z]+;然后在两端加上括号,最后把后一个‘the’替换为特殊的元字符序列1,就得到了\<([A-Za-z]+) +\1\>% egrep -i '\<([a-z]+) +\1\>' files...这样就可以查找连续重复的单词。
在支持反向引用的工具软件中,括号能够“记忆”其中的子表达式匹配的文本,不论这些文本是什么,元字符序列\1都能记住它们。而且,在一个表达式中我们可以使用多个括号。再用\1、\2、\3,等来表示第一、第二、第三组括号匹配的文本。所以([A-Z])([0-9])\1\2中的\1代表[a-z]匹配的内容,而\2代表[0-9]匹配的内容。
注意:它的局限性。因为egrep把每行文字都当作一个独立部分来看待,所以如果重复单词的第一个单词在某行末尾,第二个单词在下一行的开头,这个表达式就无法找到。

2.5 转义

如果需要匹配的某个字符本身就是元字符,正则表达式会如何处理呢?例如,如果想要检索互联网的主机名ega.att.com,使用ega.att.com可能得不到正确的结果。因为.本身就是元字符,它可以匹配任何字符,包括空格。
所以,真正匹配文本中点号的元序列应该是反斜线加上点号的组合:ega\.att\.com。称为“转义的点号”,这样的办法适用于所有的元字符,不过在字符组内部无效。
还可以用\([a-zA-Z] +\)来匹配一个括号内的单词,例如(very)在开闭括号之前的反斜线消除了开闭括号的特殊意义,于是他们能够匹配文本中的开闭括号。

2.6 正则表达式的目标

一个正则表达式要么能够匹配给定文本中的某些字符,要么不能匹配。在编写正则表达式的时候,必须进行权衡:匹配符合要求的文本,同时忽略不符合要求的文本。在任何语言中,经验都是非常重要的。

2.7 变量名

程序语言标识符(变量名)只包含字母、数字以及下画线,但不能以数字开头。我们可以用[a-zA-Z_][a-zA-Z_0-9]*,来匹配。第一个字符组匹配可能出现的第一个字符,第二个(包括对应的星号)匹配余下的字符。如果标识符的长度有限制,例如最长只能是32个字符,就加入区间量词{min, max},我们可以用{0,31}来替代最后的*

2.8 引号内的字符串

匹配引号内的字符串最简单的办法是使用这个表达式"[^"]*"
两端的引号用来匹配字符串开头和结尾的引号。在这两个引号之间的文本可以包括双引号之外的任何字符。所以我们用[^"]来匹配除双引号之外的任何字符,用*来表示两个引号之间可以存在任意数目的非双引号字符。
关于引号字符串,更有用(也更复杂)的定义是,两端的双引号之间可以出现由反斜线转义的双引号,例如"nail the 2\"x4\" plank"

2.9 表示时刻的文字,例如!“9:17am”或者“12:30pm

匹配表示时刻的文字可能有不同的严格程度。

[O-9]?[0-9]:[0-9][0-9] (am|pm)

上面语句能够匹配9:17 am或者12:30 pm,但也能匹配无意义的时刻,如99:99 pm。

首先看小时数,如果小时数是一个两位数,第一位只能是1,但是1?[0-9],仍然能够匹配19(也能够匹配0),所以更好的办法应该是把小时部分分为两种情况来处理,1[012],匹配两位数,[1-9]匹配一位数,结果就是(1[012]|[1-9])
分钟数第一位数字应该是[0-5],此时第二位数字应该是[0-9]。综合起来就是(1[012]|[1-9]):[0-5][0-9] (am|pm)

2.10 总结

第一,第二节笔记学习了以下内容:
在这里插入图片描述
几点注意事项:
1、各个egrep程序是有差别的。它们支持的元字符,以及这些元字符的确切含义,通常都有差别—要参考相应的文档。
2、使用括号的3个理由是:限制多选结构、分组和捕获文本。
3、字符组的特殊性在于,关于元字符的规定是完全独立于正则表达式语言“主体”的。
4、多选结构和字符组是截然不同的,它们的功能完全不同,只是在有限的情况下,它们的表现相同。
5、排除型字符组同样是一种“肯定断言”一即使它的名字里包含了“排除”两个字,它仍然需要匹配一个字符。只是因为列出的字符都会被排除,所以最终匹配的字符肯定不在列出的字符之内。
6、-i参数很有用,它能进行忽略大小写的匹配。
7、转义有3种情况:
\加上元字符,表示匹配元字符所使用的普通字符(例如*匹配普通的星号)。
\加上非元字符,组成一种新的有其规定意义的元字符序列(例如,\<表示“单词的起始边界”)。
\加上任意其他字符,默认情况就是匹配此字符(也就是说,反斜线被忽略了)。
对大多数版本的egrep来说,字符组内部的反斜线没有任何特殊意义,所以此时它并不是一个转义字符。
8、由星号和问号限定的对象在“匹配成功”时可能并没有匹配任何字符。即使什么字符都不能匹配到,它们仍然会报告“匹配成功”。

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值