gpt4 book ai didi

regex - Tempered Greedy Token - 将点放在负前瞻之前有什么不同?

转载 作者:行者123 更新时间:2023-12-03 14:30:52 24 4
gpt4 key购买 nike

<table((?!</table>).)*</table>
匹配我所有的表格标签。然而,
<table(.(?!</table>))*</table>
才不是。如果我尝试用文字写出表达式,第二个似乎是有道理的,但我无法理解第一个。
有什么不同 ?
作为引用,我从这里得到了“Tempered Greedy Token”这个词: Tempered Greedy Token Solution

最佳答案

什么是 Tempered Greedy Token?
rexegg.com tempered greedy token 引用非常简洁:

In (?:(?!{END}).)*, the * quantifier applies to a dot, but it is now a tempered dot. The negative lookahead (?!{END}) asserts that what follows the current position is not the string {END}. Therefore, the dot can never match the opening brace of {END}, guaranteeing that we won't jump over the {END} delimiter.


就是这样:一个 调和的贪婪 token 是一种字符序列 的否定字符类(参见单个字符的 negated character class)。
注意 :经过调和的贪婪标记和否定字符类之间的区别在于,前者除了序列本身之外并不真正匹配文本,而是不匹配不开始该序列的单个字符。 IE。 (?:(?!abc|xyz).)+ 不会匹配 def 中的 defabc ,但会匹配 defbc ,因为 a 启动了禁止的 abc 序列,而 bc 不匹配。
它包括:
  • (?:...)* - 一个量化的非捕获组(它可能是一个捕获组,但捕获每个单独的字符没有意义)(一个 * 可以是 + ,这取决于是否需要空字符串匹配)
  • (?!...) - 负前瞻,实际上对当前位置右侧的值施加了限制
  • . -(或任何(通常是单个)字符)消费模式。

  • 但是,我们总是可以通过在否定前瞻中使用交替(例如 (?!{(?:END|START|MID)}) )或通过将全匹配点替换为否定字符类(例如 (?:(?!START|END|MID)[^<>]) 尝试仅匹配标签内的文本)来进一步调整 token 。
    消耗部件放置
    请注意,没有提到在前瞻之前放置消耗部分(原始回火贪婪 token 中的点)的构造。 Avinash 的回答清楚地解释了该部分: (.(?!</table>))* 首先匹配任何字符(但没有 DOTALL 修饰符的换行符),然后检查它是否没有跟随 </table> 导致无法匹配 e 中的 <table>table</table> 。 *消耗部分( .) 必须放在回火前瞻之后
    我们什么时候应该使用经过调和的贪婪 token ?
    Rexegg.com 给出了一个想法:
  • 当我们想要匹配分隔符 1 和分隔符 2 之间的文本 block 且中间没有子字符串 3 时(例如 {START}(?:(?!{(?:MID|RESTART)}).)*?{END}
  • 当我们想要匹配包含特定模式的文本 block 而不溢出后续 block 时(例如,而不是像 <table>.*?chair.*?</table> 中的惰性点匹配,我们会使用类似 <table>(?:(?!chair|</?table>).)*chair(?:(?!<table>).)*</table> 的东西)。
  • 当我们想要匹配两个字符串之间可能的最短窗口时。当您需要从 abc 2 xyz 获取 abc 1 abc 2 xyz 时,延迟匹配将无济于事(请参阅 abc.*?xyz abc(?:(?!abc).)*?xyz )。

  • 性能问题
    缓和的贪婪 token 是资源消耗的,因为在与消耗模式匹配的每个字符之后执行前瞻检查。 Unrolling the loop technique 可以显着提高缓和的贪婪 token 性能。
    比如说,我们要匹配 abc 1 abc 2 xyz 3 xyz 中的 abc 2 xyz。而不是检查abcxyz之间的每个字符与 abc(?:(?!abc|xyz).)*xyz 的,我们可以跳过不ax[^ax]*所有字符,然后匹配所有a未遵循与bc(与a(?!bc))和所有x未遵循与yz (与 x(?!yz) ): abc[^ax]*(?:a(?!bc)[^ax]*|x(?!yz)[^ax]*)*xyz

    关于regex - Tempered Greedy Token - 将点放在负前瞻之前有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30900794/

    24 4 0