详解正则表达式后面不要包含指定的字符串内容

所属分类: 网络编程 / 正则表达式 阅读数: 796
收藏 0 赞 0 分享

以前只会/<abc(?!def).+>/.exec("<abcdef>\n<abczzz>"),匹配到<abczzz>,这种简单的固定写法,但实际使用次数几乎趋近于0。

很多场景不能写死abc,顺理成章的就写成了/<.+(?!def).+>/.exec("<abcdef>\n<abczzz>"),咦?咋把前面的匹配到了!从入门到放弃。

昨天(2019-04-07)随手写了一下/<(?:.(?!def))+>/.exec("<abcdef>\n<abczzz>"),原来是对.+(?!排除的字符串)这个结构能起到的作用理解错了,怪不得达不到预期,(.(?!排除的字符串))+才是正解。

留下一个未解的问题,每个字符后面排除一下的能良好工作,一堆未定长度字符后排除一下怎么就不能工作,前瞻不会和前面的+、*、{}起作用吗?解释看结尾。

:/<(?!.+def).+>/.exec("<abcdefzzz>\n<abczzz>")写法也可以。可能是结尾的.+导致的不能匹配,但这样写还是不行:/<.+(?!def)zzz>/.exec("<abcdefzzz>\n<abczzz>")。

正则表达式匹配指定内容后面要或不要包含指定的字符串内容:

•要:比较简单,写上这个要的即可
•不要:比要复杂很多,如何排除掉?

前提原则

1.表达式内固定内容的字符串能不写尽量不写,能简写的尽量简化来写(如前面写的abc部分不能写死)
2.可以少量使用前瞻(正向),后瞻(反向)基本不学,学了还要研究那些浏览器支持,不敢用,太多了也学不动。
3.NoJS(Not Only JavaScript);不仅仅是浏览器中的js;不过js的正则/exp/字面量写法简洁到没盆友(哪个语言),函数、对象、字符串统统不需要;不接受反驳。

假设待匹配的文本

htmlRaw=`
<div ***="***
  ***" class="***" ***="***">
  class=" matchX 1"
  <div ***="***
    ***" class="*** matchX ***" ***="*** excludeX ***">
    class=" matchX 2"
  </div>
  class=" matchX 3"
</div>

<div ***="***
  ***" class="***" ***="***">
  class=" matchX 4"
  <div ***="***
    ***" class="*** ***" ***="***">
    class=" matchX 5"
  </div>
  class=" matchX 6"
</div>

......
`;
//注: *** 不是固定内容,但不会出现未转义的xml实体、matchX、excludeX
//注: class=" matchX 123456"纯文本只做演示干扰之用,不应当作为特征

//如果数据对换行不敏感,应优先转换成没有换行的,大概率可以简化正则逻辑
htmlNoWrap=htmlRaw.replace(/[\r\n]+/g," ");

//正则测试代码
(/[\s\S]*/.exec(htmlRaw)||[])[0]

不要单个字符的匹配

匹配出div.matchX标签:<div ***="*** ***" class="*** matchX ***" ***="***">

可以直接使用 [^>]把matchX限定在<> HTML标记内,意思就是<>中的文本不要出现结尾的>字符。

单个字符还算简单:

//有效
/<div[^>]+matchX[^>]+>/.exec(htmlRaw)[0]

如果不限定在<>标记内,可能会匹配出界;并且这种不限定,迟早会出乱子:

//无效
/<div.+?matchX.+?>/.exec(htmlNoWrap)[0]
/<div[\s\S]+?matchX[\s\S]+?>/.exec(htmlRaw)[0] //有换行符就是又长又难看

其他单个字符场景另行灵活运用。

不要一个字符串的匹配

匹配出第一层不带excludeX文本内容的第一块div,就是返回包含matchX 4的那块div

[^]语法只能排除掉单个字符,不要一个字符串咋办?硬是要写成[^abc],会把a、b、c字符全部排除掉;除了使用前瞻,好像还没有别的简单办法。

使用本文开头的(.(?!排除的字符串))+结构就能达到目的,核心就在(?:[^>](?!excludeX))*:

//有效
/<div[^>]*>[^<]+<div(?:[^>](?!excludeX))*>[^<]+<\/div>[^<]+<\/div>/.exec(htmlRaw)[0]

要包含一个字符串的匹配,直接写需要的字符串即可,相对简单太多,就不写这种例子了。

未研究(.(?!排除的字符串))+结构的性能。

对于.+(?!排除)不能工作的释疑

由于(?!排除)并不会作用于贪婪匹配到的每一个字符串,只会作用于.+贪婪匹配到的最后一个字符;意思就是前瞻不能阻止+对最后一个字符之前的所有字符进行贪婪匹配。

/<.+(?!def).+>/.exec("<abcdef>\n<abczzz>")

第一个 .+ 匹配到了 abcde,之后是 f,不是 def,第二个 .+ 匹配 f,符合正则

额外记录

/(\d+)(?!\.1)/.exec("123.141") 目测是这样的:
> 123:\d+贪婪匹配到.为止
> 12:发现 123.1 不符合(?!\.1),后退一位
> 没有表达式了,返回 12

/(.+)(?!\.1)/.exec("123.141") 目测是这样的:
> 123.141:.+贪婪匹配到结尾
> 123.141 : 符合(?!\.1)
> 没有表达式了,返回 123.141

/(.(?!\.1))+/.exec("123.141") 目测是这样的:
> 1:.匹配到新的一位
> 1:123 符合(?!\.1)
> 12:.匹配到新的一位
> 12:123.符合(?!\.1)
> 123:.匹配到新的一位
> 12:发现 123.1 不符合(?!\.1),后退一位,并退出循环
> 没有表达式了,返回 12

如果要对每个字符进行前瞻检查,唯有最后一种写法比较好理解。

以上所述是小编给大家介绍的正则表达式后面不要包含指定的字符串内容,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

正则表达式验证IPV4地址功能实例分析

这篇文章主要介绍了正则表达式验证IPV4地址功能,结合实例形式分析了IPV4地址验证的原理及具体实现技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

正则表达式教程之前后查找lookaround详解

这篇文章主要介绍了正则表达式教程之前后查找lookaround,结合具体问题分析了向前查找及向后查找功能的实现技巧与注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

正则匹配密码只能是数字和字母组合字符串功能【php与js实现】

这篇文章主要介绍了正则匹配密码只能是数字和字母组合字符串功能,涉及针对字符、数字等正则操作相关技巧,并给出了php与js实现示例,需要的朋友可以参考下
收藏 0 赞 0 分享

正则验证不能含有中文的实现方法【jQuery与java实现】

这篇文章主要介绍了正则验证不能含有中文的实现方法,结合jQuery与java两种实现方法分析了针对中文的正则验证操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

JS 密码强度校验的正则表达式(简单且好用)

最近在做一个通行证的项目,在项目中有这样的需求,注册模块中输入密码需要显示密码强度,今天小编给大家分享JS 密码强度校验的正则表达式,简单好用,需要的朋友参考下
收藏 0 赞 0 分享

iOS 正则表达式判断纯数字及匹配11位手机号码的方法

这篇文章主要介绍了iOS 正则表达式判断纯数字及匹配11位手机号码的方法,判断手机号码是否正确的方法很多,我是用正则表达式来完成匹配的,具体方法,大家参考下本文
收藏 0 赞 0 分享

正则表达式(简单易懂篇)

正则表达式是一种可以用于模式匹配和替换的强大工具。这篇文章主要介绍了正则表达式(简单易懂篇),需要的朋友参考下
收藏 0 赞 0 分享

正则表达式实现匹配连续数字的方法

我这两天刚刚学正则表达式。我觉的正则对连续的字符匹配很简单,但是对连续的一段数字匹配就不是很好。正好最近有朋友问了匹配连续数字的正则,就帮忙写了一下,算是当作温习一下吧。下面这篇文章就主要介绍了正则表达式实现匹配连续数字的方法。
收藏 0 赞 0 分享

正则表达式简介及在C++11中的简单使用教程

正则表达式(regular expression)是计算机科学中的一个概念,又称规则表达式,通常简写为regex、regexp、RE、regexps、regexes、regexen。接下来通过本文给大家介绍正则表达式简介及在C++11中的简单使用教程,一起通过本文学习吧
收藏 0 赞 0 分享

正则表达式实现最小匹配功能的方法

这篇文章主要介绍了正则表达式实现最小匹配功能的方法,结合具体实例形式分析了正则表达式最小匹配功能的原理与实现技巧,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多