《正则表达式必知必会》Part 2

又是一阵的瞎逼忙,之前打算要整理完的正则表达式一直拖到现在,还是要提高效率。这段时间一直在做用户日志文件处理,用上了很多正则表达式,乘热打铁把这些东西整理完。

§ 重复匹配

  • 有多个匹配

匹配一个或多个字符:元字符+ 匹配在其前面的字符或者模式一个或多次(至少一次,不匹配零次的情况)。例如,匹配abc@abc.def.com ,可以使用\w@[\w.]+\.\w+ 。在字符集合中元字符将被解释为普通字符,但转移了也没有坏处,此外匹配字符本身需要转义。

匹配零个或多个字符:元字符* 匹配在其前面的字符或者模式零次或多次,用法同上。

匹配零个或一个字符:元字符? 匹配在其前面的字符或者模式零次或一次,用法同上。

  • 匹配的重复次数

为重复匹配次数设定一个精确的值:正则表达式语言提供了一个用来设定_重复次数_(interval)的语法,重复次数用{} 字符括起来给出。如果你想为重复匹配次数设定一个精确的值,把那个数字写在两个字符之间即可。例如,匹配一个RGB色值可以使用如下模式[0-9A-Fa-f]{6} ,这样即可匹配6位的色值。

为重复匹配次数设定一个区间:这样的语法还可以用来给匹配次数设定一个区间,即设定一个最小值和一个最大值。例如,{2,4} 的含义是最少重复2次、最多重复4次。

匹配“至少重复多少次”:这种情况下只需给出一个最小值但不必给出最大值。例如,{3,} 表示至少重复3次,并不设上限,即必须重复3次或者更多。

  • 防止过度匹配

这里介绍的.+{n,} 在重复次数上面没有上限值,而这样做有时会导致过度匹配现象。因为.+ 都是所谓的“贪婪型”元字符,他们在进行匹配时的行为模式是多多益善而不是适可而止。在不需要这些“贪婪行为”的时候,只需要在相应贪婪型元字符后面加上一个? 后缀即可。在这里“懒惰”意味着匹配尽可能少的字符,与之相反的“贪婪”则匹配尽可能多的字符。

§ 位置匹配

  • 单词边界

这是最常用的边界,由限定符\b 指定单词边界,用它来匹配单词的开始或结尾。这个位置其实就是位于一个能够构成单词的字符和一个不能用来构成单词的字符之间。另外\B-\B 可以匹配一个前后都不是单词边界的连字符即前后都有多余空格的连字符。

  • 字符串边界

用来定义字符串边界的元字符有两个:一个是用来定义字符串开头的^ ,另一个是用来定义字符串结尾的 的用法与^ 完全一致。例如,在一份web页面中,</html> 之后应该不再有任何实际内容,可以用这个模式来匹配</[Hh][Tt][Mm][Ll]>\s*$

?m 记号十一个能够改变其他元字符行为的元字符序列来启用分行匹配模式(multiline mode),例如,匹配代码中单独为一行以// 开头的代码注释,可以而使用(?m)^\s*//.*$ 模式。

§ 使用子表达式

子表达式是一个更大的表达式的一部分;把一个表达式划分一系列子表达式的目的是为了把那些子表达式当做一个独立元素来使用。子表达式必须用() 括起来。

子表达式允许嵌套包括多层嵌套,子表达式常见的用途包括:对重复次数元字符的作用对象做出精确的设定和控制、对| 操作符的OR条件做出准确的定义等。

§ 回溯引用:前后一致匹配

回溯引用指的是模式的后半部分引用在前半部分中定义的子表达式。使用\1\2\3代表回溯引用第123个表达式(不同环境符号可能不同)。Java中Matcher.group(0)对应着第一个匹配。回溯引用只能用来引用模式里的子表达式。回溯引用匹配通常从1开始计数,第0个匹配代表整个正则表达式。例如,JS中可以有如下用法<[Hh]([1-6])>.*?</[Hh]\1> 来匹配标题,在JS中使用反斜杠来表示回溯引用,不同的实现中差异较大,需查阅相关资料。

回溯引用在文本匹配和文本替换操作里非常有用,同时大小写转换也是类似的思路:

\E :(结束\L\U 转换)

\l :(把下一字符转小写)

\L :(把\L\E 间字符全部转小写)

\u :(把下一字符转大写)

\U :(把\U\E 间字符全部转大写)

§ 前后查找

前后查找(lookaround),对某一位置的前后内容进行查找。其中的前后指模式与被查找文本的相对位置而言,左为前。

向前查找制定了一个必须匹配但不在结果中返回的模式。使用模式(?=) ,向前(左)匹配,返回匹配值不含= 后内容(不消费)。类似的向后匹配是(?<=) ,向后(右)匹配。例如,匹配网页的标题可用(?<=(<[Tt][Ii][Tt][Ll][Ee]>)).*(?=(</[Tt][Ii][Tt][Ll][Ee]>)) 模式。

向前查找和向后查找通常用来匹配文本,其目的是为了确定将被返回为匹配结果的文本位置(通过指定匹配结果的前后必须是那些文本)。称“正向前查找(positive lookahead)”和“正向后查找(positive lookbehind)”。我们还可以对前后查找取非来查找不与给定的模式匹配的文本。

(?=) :正向前查找

(?<=) :正向后查找

(?!) :负向前查找

(?<!) :负向后查找

§ 嵌入条件

正则表达式里条件用? 来定义嵌入条件,嵌入条件不外乎两种情况:①根据一个回溯引用来进行条件处理②根据一个前后查找来进行条件处理。相关语法为(?(regex)true_regex|false_regex) 很像三项表达式,即如果条件成立则执行成立的相关模式,不成立则执行不成立的相关模式。

0%