之前只会
/<abc(?!def).+>/.exec("<abcdef>\n<abczzz>")
,匹配到<abczzz>
,这种简单的固定写法,但实际使用次数几乎趋近于0。javascript不少场景不能写死
abc
,瓜熟蒂落的就写成了/<.+(?!def).+>/.exec("<abcdef>\n<abczzz>")
,咦?咋把前面的匹配到了!从入门到放弃。html昨天(2019-04-07)随手写了一下
/<(?:.(?!def))+>/.exec("<abcdef>\n<abczzz>")
,原来是对.+(?!排除的字符串)
这个结构能起到的做用理解错了,怪不得达不到预期,(.(?!排除的字符串))+
才是正解。java留下一个未解的问题,每一个字符后面排除一下的能良好工做,一堆未定长度字符后排除一下怎么就不能工做,前瞻不会和前面的
+、*、{}
起做用吗?解释看结尾。正则表达式
附:
/<(?!.+def).+>/.exec("<abcdefzzz>\n<abczzz>")
写法也能够。多是结尾的.+致使的不能匹配,但这样写仍是不行:/<.+(?!def)zzz>/.exec("<abcdefzzz>\n<abczzz>")
。浏览器
正则表达式匹配指定内容后面要或不要包含指定的字符串内容:函数
- 要:比较简单,写上这个要的便可
- 不要:比要复杂不少,如何排除掉?
abc
部分不能写死)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标记内,意思就是<>
中的文本不要出现结尾的>
字符。测试
单个字符还算简单:code
//有效 /<div[^>]+matchX[^>]+>/.exec(htmlRaw)[0]
若是不限定在<>
标记内,可能会匹配出界;而且这种不限定,早晚会出乱子:xml
//无效 /<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
若是要对每一个字符进行前瞻检查,惟有最后一种写法比较好理解。