以前只会 /<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>").
正则表达式匹配指定内容后面要或不要包含指定的字符串内容:
要: 比较简单, 写上这个要的即可
不要: 比要复杂很多, 如何排除掉?
前提原则
表达式内固定内容的字符串能不写尽量不写, 能简写的尽量简化来写(如前面写的 abc 部分不能写死)
可以少量使用前瞻 (正向), 后瞻(反向) 基本不学, 学了还要研究那些浏览器支持, 不敢用, 太多了也学不动.
- 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[^>]+>/.exec(htmlRaw)[0]
- // 无效
- /<div.+?matchX.+?>/.exec(htmlNoWrap)[0]
- /<div[\s\S]+?matchX[\s\S]+?>/.exec(htmlRaw)[0] // 有换行符就是又长又难看
- // 有效
- /<div[^>]*>[^<]+<div(?:[^>](?!excludeX))*>[^<]+<\/div>[^<]+<\/div>/.exec(htmlRaw)[0]
来源: https://www.cnblogs.com/xiangyuecn/p/10668378.html