四时宝库

程序员的知识宝库

当regexp正则表达式遇到零宽断言:一场关于“位置”的精准狩猎

正则表达式的基础外壳函数(wps版):

REGEXP函数是基于正则表达式,对复杂文本进行匹配、提取和替换的函数。


基本语法结构:

REGEXP(原始字符串,正则表达式,[匹配模式],[替换内容])


匹配模式是可选项,0或忽略表示提取,1表示判断是否包含,2表示替换。

替换内容是可选项,仅在匹配模式为2时有效,用来替换匹配的内容。


我们通过编写不同的正则表达式来实现不同的复杂需求



最近自学REGEXP函数的正则表达式知识,总是从资料中看到“零宽断言”的字眼,对它的概念是百思不得其解。今天我们就下决心再次深入细致的了解一下,毕竟入门正则表达式,是绕不开它的。



零宽断言(Lookaround Assertions)用于匹配符合条件的位置而非具体字符,不占用匹配字符长度。


零宽断言分为4种类型


类型、符号以及功能:

(?=) 正向先行断言

右侧必须出现指定模式

通俗讲:必须以某固定字符结尾


(?!) 负向先行断言

右侧不得出现指定模式

通俗讲:必须不能以某固定字符结尾


(?<=) 正向后行断言

左侧必须出现指定模式

通俗讲:必须以某固定字符开头


(?<!) 负向后行断言

左侧不得出现指定模式

通俗讲:必须不能以某固定字符开头



当然了,概念固然重要,因为它是我们灵活运用零宽断言的前提。但如果我们再结合具体的案例,就会对使用这个零宽断言起到事半功倍的效果。



我们通过下面一个例子理解(?=) 正向先行断言与(?<=) 正向后行断言。


如下图所示:

我们想要提取A2单元格括号内容,但最终不显示括号符号。也就是说括号内容是:“(red)”,“(green)”,“(blue)”,但最终不要显示括号为:“red”,“green”,“blue”。



我们这样提取括号内容。


输入公式:

=REGEXP(A2,"\(.+\)")


\:代表转义符。

\(:表示转义左括号。

\):表示转义右括号。

因为括号(英文半角下)在正则中有其独特的含义,这里表示真正的普通括号,为了避免使用冲突,须要转义。


.:点号代表任意的单个字符(除换行符)

+:代表重复前面元素的1次或多次。

.+:表示任意的多个字符。


\(.+\):完整表示括号里面的任意的多个字符。


此时默认贪婪模式匹配到多余的内容



转换为懒惰模式:

=REGEXP(A2,"\(.+?\)")


在量词符“.+”后面加上一个问号?,使其变成懒惰模式。这样它会在匹配到第一个符合要求的数据“(red)”后,停止工作,自动去匹配下一个符合要求的数据“(green)”,然后再次停止工作,自动匹配最后一个符合要求的数据“(blue)”,直至全部匹配完结束。


此时虽然匹配结束,但得到的括号内容并没有去掉括号



重点来了,我们使用(?=) 正向先行断言

=REGEXP(A2,"\(.+?(?=\))")


右侧必须出现指定模式,比如说匹配到的其中一个括号内容:“(red)”,而“(red”的右侧必须出现指定的右括号“)”,但不占用匹配字符长度,即不显示“)”。


所以我们对表达式中右括号“\)”加上正向先行断言“(?=\))”,即内容的右侧必须是右括号但不显示它,这样就相当于去掉了右括号。



我们继续使用(?<=) 正向后行断言

=REGEXP(A2,"(?<=\().+?(?=\))")


左侧必须出现指定模式,比如上一步得到的匹配结果是去掉右括号的内容:“(red”,而“red”的左侧必须出现指定的左括号“(”,但不占用匹配字符长度,即不显示“(”。


所以我们对左括号“\(”加上正向后行断言“(?<=\()”,即内容的左侧必须是左括号但不显示它,这样就相当于去掉了左括号。


至此左括号与右括号就都不显示了




我们通过下面的一个例子理解(?<!) 负向后行断言


比如我们要提取的数字有一个特点,就是数字的前面必须不能为A。


可以先提取数字:

=REGEXP(A2,"\d+")


\d+:表示任意的多个数字。


此时所有数字都被提取到了。



我们对左侧的A加上负向后行断言:

=REGEXP(A2,"(?<!A)\d+")


(?<!):负向后行断言,左侧不得出现指定模式

(?<!A)\d+:表示任意数字的左侧必须不能是A。数字1的前面是A,所以不符合,只有数字26的左侧符合不是A。




我们通过下面的一个例子理解(?!) 负向先行断言


比如我们要提取的数字有一个特点,就是数字的后面必须不能为A。


可以先提取数字:

=REGEXP(A2,"\d+")


\d+:表示任意的多个数字。


此时所有数字都被提取到了。



我们对右侧的A加上负向先行断言 :

=REGEXP(A2,"\d+(?!A)")


(?!):负向先行断言,右侧不得出现指定模式

\d+(?!A):表示任意数字的右侧必须不能是A。数字6的右面是A,所以不符合,只有数字12的右侧符合不是A。


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接