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

以前只会/<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,符合正则

摘自:https://www.v2ex.com/t/552813#reply13

额外记录

/(\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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • ES6学习笔记-字符串与正则表达式 JS字符串编码 在ES6之前,JS的字符串以16位字符编码(UCS-2)为基础...
    小线亮亮阅读 645评论 0 0
  • 前言 对于正则,著称火星文字,见名知意主要它晦涩难懂,一直以来,看到它总是怕怕的,在平时,也只是简单的用用,其主要...
    itclanCoder阅读 772评论 0 2
  • RegExp 三大方法本文的RegExp采用直接量语法表示:/pattern/attributes。attribu...
    恩德_b0c2阅读 461评论 0 0
  • 本文译自 制作正则引擎的作者 Jan Goyvaerts 为工具 RegexBuddy 写的教程版权归原作者所有注...
    极客圈阅读 3,290评论 0 25
  • In the meantime the wood had been alive with the sound of...
    Mr_Oldman阅读 408评论 0 1