💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
# 断言 ## **正向零宽断言** 用于**查找在某些内容(但并不包括这些内容)之前或之后的东西**,也就是说它们像\\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。最好还是拿例子来说明吧: (?=exp)也叫**零宽度正预测先行断言**,它断言自身出现的位置的后面能匹配表达式exp。比如\\b\\w+(?=ing\\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。 (?<=exp)也叫**零宽度正回顾后发断言**,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\\bre)\\w+\\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。 假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:((?<=\\D)\\D{3})+\\b,用它对xxxxxxxxxx进行查找时结果是xxxxxxxxx 下面这个例子同时使用了这两种断言:(?<=\\s)\\d+(?=\\s)匹配以空白符间隔的数字(再次强调,不包括这些空白符) 断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配。 ## **负向零宽断言** 如果我们只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样: \\b\\w\*q\[^u\]\\w\*\\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为\[^u\]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的\[^u\]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\\w\*\\b将会匹配下一个单词,于是\\b\\w\*q\[^u\]\\w\*\\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。,我们可以这样来解决这个问题:\\b\\w\*q(?!u)\\w\*\\b。 零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\\d{3}(?!\\d)匹配三位数字,而且这三位数字的后面不能是数字;\\b((?!abc)\\w)+\\b匹配不包含连续字符串abc的单词。 同理,我们可以用(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<!\[a-z\])\\d{7}匹配前面不是小写字母的七位数字。 请详细分析表达式(?).\*(?=),这个表达式最能表现零宽断言的真正用途。 一个更复杂的例子:(?).\*(?=)匹配不包含属性的简单HTML标签内里的内容。(?)指定了这样的前缀:被尖括号括起来的单词(比如可能是),然后是.\*(任意的字符串),最后是一个后缀(?=)。注意后缀里的\\/,它用到了前面提过的字符转义,将”/“转义;\\1则是一个反向引用,引用的正是捕获的第一组,前面的(\\w+)匹配的内容,这样如果前缀实际上是的话,后缀就是了。整个表达式匹配的是和之间的内容(再次提醒,不包括前缀和后缀本身)。 (?:)(?=)(?!)(?<=)(?<!)(?i) 零宽断言 可简单理解断言为条件 > 注意断言的pattern条件必须是固定的如例子所给,而不是(^>)\*这种 ? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多的匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少的匹配“o”,得到结果 ['o', 'o', 'o', 'o'] .点 匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。 (pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。 (?:pattern) 获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。`$subject<span class="token1">=</span><span class="token2">"industry and industries !"</span><span class="token3">;</span>$pattern<span class="token1">=</span><span class="token2">"/industr(?:y|ies)/"</span><span class="token3">;</span>$a<span class="token1">=</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span> $subject<span class="token3">,</span> $matches<span class="token3">,</span> PREG_OFFSET_CAPTURE<span class="token3">)</span><span class="token3">;</span><span class="token4">dump</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span>结果:array<span class="token3">:</span><span class="token6">1</span> <span class="token3">[</span>▼ <span class="token6">0</span> <span class="token1">=</span><span class="token1">></span> array<span class="token3">:</span><span class="token6">2</span> <span class="token3">[</span>▼ <span class="token6">0</span> <span class="token1">=</span><span class="token1">></span> array<span class="token3">:</span><span class="token6">2</span> <span class="token3">[</span>▼ <span class="token6">0</span> <span class="token1">=</span><span class="token1">></span> <span class="token2">"industry"</span> <span class="token6">1</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">0</span> <span class="token3">]</span> <span class="token6">1</span> <span class="token1">=</span><span class="token1">></span> array<span class="token3">:</span><span class="token6">2</span> <span class="token3">[</span>▼ <span class="token6">0</span> <span class="token1">=</span><span class="token1">></span> <span class="token2">"industries"</span> <span class="token6">1</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">13</span> <span class="token3">]</span> <span class="token3">]</span><span class="token3">]</span>` find(?=pattern) (**零宽度正预测先行断言**)正向预搜索(匹配find右边是pattern的find)非获取匹配,正向肯定预查,该匹配不需要获取供以后使用。例如判断Windows右侧是否出现pattern出现则匹配,“Windows(?=95|98|NT|2000)”能匹配“Windows95、Windows98、Windows2000、WindowsNT”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 `$str<span class="token1">=</span>"<span class="token4">fgets</span><span class="token3">(</span><span class="token3">)</span><span class="token4">fgetss</span><span class="token3">(</span><span class="token3">[</span>\\\$allowable_tags <span class="token3">]</span> <span class="token3">)</span>"<span class="token3">;</span>``$pattern<span class="token1">=</span><span class="token2">"/[\w]+(?=[(])/"</span><span class="token3">;</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span>$str <span class="token3">,</span>$matches<span class="token3">)</span><span class="token3">;</span>` find(?!pattern) (**零宽度负预测先行断言**)正向预搜索(匹配find右边不是pattern的find)非获取匹配,正向否定预查,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。 ``` <pre class="calibre17">\b((?!abc)\w)+\b:匹配由字母或数字或下划线或汉字组成的字串,但字串中不能出现abc ``` (?<=pattern)find (**零宽度正回顾后发断言**)反向预搜索(匹配find左边是pattern的find) 匹配pattern后面的位置 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 例子:取出【】里的内容 `$strSubject <span class="token1">=</span> <span class="token2">"abc【111】abc【222】abc【333】abc"</span><span class="token3">;</span>$strPattern <span class="token1">=</span> <span class="token2">"/(?<=【)[^】]+/"</span><span class="token3">;</span>$arrMatches <span class="token1">=</span> <span class="token3">[</span><span class="token3">]</span><span class="token3">;</span><span class="token4">preg_match_all</span><span class="token3">(</span>$strPattern<span class="token3">,</span> $strSubject<span class="token3">,</span> $arrMatches<span class="token3">)</span><span class="token3">;</span><span class="token4">var_dump</span><span class="token3">(</span>$arrMatches<span class="token3">)</span><span class="token3">;</span>` (?<!pattern)find (**零宽度负回顾后发断言**) 反向预搜索(匹配find左边不是pattern的find) 匹配前面不是pattern的位置 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题 此处用或任意一项都不能超过2位,如“(?<!95|98|NT|20)Windows正确,“(?<!95|980|NT|20)Windows 报错,若是单独使用则无限制,如(?<!2000)Windows 正确匹配