马黑黑 发表于 2023-1-16 11:44

正则表达式之负向先行断言

<style>
#mydiv { #with: 600px; }
#mydiv >p { margin: 10px 0; padding: 0; }
</style>

<h2>正则表达式:负向先行断言</h2>
<div id="mydiv">
        <p>Windows95</p>
        <p>Windows 95</p>
        <p>Windows98</p>
        <p>Windows 98</p>
        <p>WindowsME</p>
        <p>Windows ME</p>
        <p>Windows2000</p>
        <p>Windows 2000</p>
        <p>WindowsXP</p>
        <p>Windows XP</p>
        <p>Windows7</p>
        <p>Windows 7</p>
        <p>Windows10</p>
        <p>Windows 10</p>
                <p>Windows11</p>
        <p>Windows 11</p>
</div>
<p><button id="btn" type="button">Okey</button> <input id="pipei" type="text" value="Windows(?!95)"/></p>

<script>

btn.onclick = () => {
        let str = mydiv.innerHTML;
        str = str.replace(/<\/?span[^>]*>/g,''); //去除 span 标签
        let reg = new RegExp(pipei.value.trim(), 'g');
        let ar = str.match(reg);
        if (ar) {
                mydiv.innerHTML = str.replace(reg,'<span style="color: red">$&</span>');
        }
}

</script>

马黑黑 发表于 2023-1-16 12:01

负向先行断言

表达式(?!子表达式)

例:

Windows(?!95)

Windows 是被匹配的表达式。圆括号是否定性质的先行断言,用以限制前面的表达式,其中:?! 表示不能等于,95 是字面量,不能等于的值。整个正则表达式的意思是,如果有这么一个带检索字符串,Windows 后面不等于 95 ,则这个字符串的 Windows 匹配这个正则表达式。

负向先行断言又称否定先行断言,和正向先行断言(又称肯定先行断言)不同,子表达式的引导符号是 ?!,等号 = 变成了感叹号 ! 。在编程世界,= 表示等于即肯定,! 表示否定,JS里不等于就写成 != ,但这里是正则的负向先行断言,?! 是引导词,表示不能等于其后面的值(例如 95)。

负向先行断言的子表达式是以否定的形式来匹配(或曰限制)其前面的主表达式,Windows(?!95) 这个正则表达式表示,我要去匹配 Windows 后面不是紧跟着 95 的 Windows,如此,我们的演示框里,除了 Windows95 这一行,其余的都匹配,都会标红。

负向先行断言中的子表达式有否定意味,JS之前对其是不支持的,现在主流浏览器已经支持,但估计仍有问题。我的经验是,使用否定式先行断言,主表达式不要弄成复杂的,最好就是一个字面量表达式,子表达式则可以设置为稍微复杂一点的。试看下面的式子:

Windows(?!\s?2000)

这个式子,子表达式 (?!\s?2000) 里,?! 是引导词,不能等于。\s? 是或没有或有一个的空格,后面是 2000 ,\s?2000 是一个组合单位,(?!\s?2000) 整体就是先行断言子表达式,用以限制前面的主表达式,意为:Windows 后面如果不是紧跟着带空格或不带空格的 2000 的,就匹配。

下面是在上面式子基础上做了一些改动:

Windows(?!\s?(2000|98))

这里,子表达式有了嵌套,\s? 是一个单元,表示可有可无的空格,(2000|98)是另一个单元,2000 或 98,整个子表达式 (?!\s?(2000|98)) 的意思就是,不许主表达式 Windows 去匹配带空格或不带空格的 2000 或 98,大家可以去演示楼试一下。

樵歌 发表于 2023-1-16 13:52

找个懂王来说道说道。{:4_173:}

红影 发表于 2023-1-16 15:12

先行断言几个字是直译来的吧,内容大概有点感觉了,毕竟前面看过正向的,这个词汇看着有点难受{:4_173:}

红影 发表于 2023-1-16 15:14

有这个负向先行断言也挺好,毕竟有时需要去掉一些不符合要求的,要是用正向的还得一个个去设定符合要求的大多数。所以有这个也挺方便的呢{:4_204:}

马黑黑 发表于 2023-1-16 17:05

红影 发表于 2023-1-16 15:14
有这个负向先行断言也挺好,毕竟有时需要去掉一些不符合要求的,要是用正向的还得一个个去设定符合要求的大 ...

它的出现总是因为需求吧。比方说给一长串数字加千分位分隔符,用断言就比较省事

马黑黑 发表于 2023-1-16 17:05

樵歌 发表于 2023-1-16 13:52
找个懂王来说道说道。

去找特朗普

马黑黑 发表于 2023-1-16 17:07

红影 发表于 2023-1-16 15:12
先行断言几个字是直译来的吧,内容大概有点感觉了,毕竟前面看过正向的,这个词汇看着有点难受

意译,但和直译也没多大区别,毕竟这是严谨的概念,描述都是精准的。

红影 发表于 2023-1-16 20:41

马黑黑 发表于 2023-1-16 17:05
它的出现总是因为需求吧。比方说给一长串数字加千分位分隔符,用断言就比较省事

嗯嗯,肯定是应需求而出现的。到后来越出现越多,学习起来就不容易了。

红影 发表于 2023-1-16 20:44

马黑黑 发表于 2023-1-16 17:07
意译,但和直译也没多大区别,毕竟这是严谨的概念,描述都是精准的。

嗯嗯,知道了{:4_204:}

马黑黑 发表于 2023-1-16 21:10

红影 发表于 2023-1-16 20:44
嗯嗯,知道了

{:4_190:}

马黑黑 发表于 2023-1-16 21:10

红影 发表于 2023-1-16 20:41
嗯嗯,肯定是应需求而出现的。到后来越出现越多,学习起来就不容易了。

没错

红影 发表于 2023-1-16 21:56

马黑黑 发表于 2023-1-16 21:10
没错

不过这些也是一路走过来的成绩,很不容易的。

樵歌 发表于 2023-1-16 22:05

马黑黑 发表于 2023-1-16 17:05
去找特朗普

他有麻烦了{:4_190:}

马黑黑 发表于 2023-1-16 22:07

樵歌 发表于 2023-1-16 22:05
他有麻烦了

白等一样有麻烦,同样的

马黑黑 发表于 2023-1-16 22:09

红影 发表于 2023-1-16 21:56
不过这些也是一路走过来的成绩,很不容易的。

{:4_190:}

红影 发表于 2023-1-17 14:05

马黑黑 发表于 2023-1-16 22:09


谢咖啡{:4_204:}

马黑黑 发表于 2023-1-17 17:35

红影 发表于 2023-1-17 14:05
谢咖啡

客气了,随意就好

红影 发表于 2023-1-17 21:21

马黑黑 发表于 2023-1-17 17:35
客气了,随意就好

没客气呢,本来就是随意地谢了一下{:4_173:}

马黑黑 发表于 2023-1-17 22:27

红影 发表于 2023-1-17 21:21
没客气呢,本来就是随意地谢了一下

那也是挺客气的
页: [1] 2
查看完整版本: 正则表达式之负向先行断言