K:正则表达式之进阶
子表达式:
前面所介绍的关于重复匹配的知识,其重复匹配的字符只作用于紧挨着的前一个字符而言,而有时候要将一个集体(姑且用该概念进行称呼)进行重复多遍的进行匹配,则使用前面所介绍的知识,其是无法做到的。为此,使用了子表达式的概念。子表达式是一个更大的表达式的一部分,把一个表达式划分为一系列子表达式的目的是为了把那些子表达式当作一个独立元素来进行使用。子表达式,用(和)括起来,其()中的内容表示一个整体。其中如果要匹配字符(和字符),则必须要对其进行转义,即使用\(和\)用于匹配字符“(”和字符“)”。
-
表达式(\d{1,3}\.){2}其等价于\d{1,3}\.\d{1,3}\.
-
子表达式运行进行嵌套,实际上,子表达式允许进行多重嵌套。这种嵌套层次在理论上并没有限制。
-
|用于表示选择,其将|前面的字符和|后面的字符都当成一个整体来进行对待。例如19|20,表示19和20两个部分中的其中之一,需要注意的是19|20\d{2}表示的是19和20\d{2}这两部分。如果需要用其来匹配19或者20开头的四位年份的话,需要将其写为(19|20)\d{2}的形式。如果要匹配|字符本身,需要对其进行转义,即“\|”用于匹配字符“|”本身
-
子表达式的用途之一回溯引用(backreference)
回溯引用指的是模式的后半部分引用在前半部分中定义的子表达式,回溯引用允许正则表达式模式引用前面匹配的结果。考虑一个问题,假如你有一段文本,你先把这段文本里所以连续重复出现的单词使用正则表达式来给其找出来。显然,在搜索某个单词的第二次出现时,这个单词必须是已知的,否则无法找出其重复的单词。
-
使用回溯引用的一个例子:
文本:this is a block of of text,several words here are are repeated,and and they should not be.
正则表达式:[ ]+(\w+)[ ]+\1
匹配结果:this is a block of of text,several words here are are repeated,and and they should not be.
解析:[ ]+用于匹配1到多个空格,\w+用于匹配一个或多个字母数字字符,[ ]+匹配随后的空格。需要注意的是\w+是一个子表达式,其并不涉及重复匹配的问题,这个子表达式只是把整个模式的一部分单独划分出来以便在后面进行引用。这个模式的最后一部分为\1,这是一个回溯引用,而它引用的正是前面所划分出来的那个子表达式,当(\w+)匹配到of的时候,\1也匹配of,当(\w+)匹配and的时候,\1也匹配and。\1表示模式里的第一个子表达式匹配的结果,\2表示模式里第二个子表达式匹配的结果,\3表示第三个子表达式匹配的结果,以此类推。需要注意的是,不同的正则表达式的实现在实现回溯引用的时候,在语法方面存着差异。回溯引用只能用来引用模式里的子表达式,同时,回溯引用匹配通常从1开始计数,在许多实现中,第0个匹配即\0用来代表整个表达式。
-
大小写转换
-
\E用于结束\L或\U转换
-
\L用于把\L和\E之间的字符全部转换为小写
-
\l用于把下一个字符转换为小写
-
\u用于把下一个字符转换为大写
-
\U用于把\U和\E之间的字符全部转换为大写
以上的这些元字符主要应用与正则表达式的替换应用中,正则表达式除了用于搜索(字符串模式匹配)之外,其另一个主要的作用便是进行文本替换。在进行替换的时候,可以使用回溯引用对符合搜索模式的进行字符串进行引用
-
前后查找
有时候,我们需要用正则表达式标记要匹配的文本的位置(而不仅仅是文本本身)。这就引出了前后查找的概念(lookaround,对某一位置的前后内容进行查找),前后查找分为向前查找和向后查找两部分内容。需要注意的是,前后查找中的前、后模式与被查找文本的相对位置而言,左为前
-
向前查找
向前查找指定一个必须匹配但不在结果中返回的模式。向前查找实际就是一个子表达式,而且从格式上看也确实如此。从语法上看,向前查找模式其实就是一个以?=开头的子表达式,需要匹配的文本跟在=后面。向前查找,用于查找(?=)之前的文本,(?=)子表达式需要写在其它正则表达式语句之后如.*(?=:)
例子如下:
文本:
正则表达式:
.*(?=:)
匹配结果:
http https
正则表达式修改为:
.*(😃
匹配结果:
http: https:
-
向后查找:
向后查找的概念和向前查找的概念差不多,值不过一个是查找向前查找操作符之前的文本,一个是查找向后查找操作符之后的文本。向后查找操作符是?<=,向后查找操作符和向前查找操作符一样,必须要用在一个子表达式里,而且后面跟要进行匹配的文本。向后查找的子表达式(?<=)需要写在其它正则表达式语句之前即如(?<=:).*
前后查找也可以使用!进行取非操作。(?!)表示负向前查找,(?<!)表示负向后查找,其分别表示不以(?!)中指定模式为结尾的的字符以及不以(?<!)中指定模式为开头的字符
-
嵌入条件
正则表达式的另一个不常使用的强大功能是在表达式的内部嵌入条件处理功能。需要注意的是,并非所有的正则表达式实现都支持条件处理。
正则表达式里的条件要用?来进行定义。嵌入条件的使用不外乎有如下两种情况:
1.根据一个回溯引用来进行条件处理
2.根据一个前后查找来进行条件处理
-
回溯引用条件:
回溯引用条件在一个前面的子表达式搜索取得成功的情况下才允许使用一个表达式。其语法格式如下(?(回溯引用)回溯引用存在时才执行的子表达式|回溯引用不存在时才执行的子表达式)需要注意的是,回溯引用的编号并不需要进行转义即?(1)这样的格式是正确的,而?(\1)这样的格式是不正确的。
-
前后查找条件:
前后查找条件只在一个向前查找或向后查找操作取得成功的情况下才允许一个表达式被使用。其语法格式和回溯引用条件的相似,只需要把回溯引用替换为一个完整的前后查找表达式即可。