Regex 向后看:雷格克斯的风靡一时?

Regex 向后看:雷格克斯的风靡一时?,regex,regex-lookarounds,lookaround,Regex,Regex Lookarounds,Lookaround,最近,许多正则表达式问题在查询中都有一些环顾四周的元素,在我看来,这对比赛的成功不是必需的。是否有一些教学资源在推广它们?我正试图找出哪种情况下,你最好采用积极的前瞻性/前瞻性。我看到的主要应用程序是在尝试不匹配元素时。但是,例如,这个来自最近一个问题的查询有一个简单的解决方案来捕获*,但是为什么要使用look back (?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span (

最近,许多正则表达式问题在查询中都有一些环顾四周的元素,在我看来,这对比赛的成功不是必需的。是否有一些教学资源在推广它们?我正试图找出哪种情况下,你最好采用积极的前瞻性/前瞻性。我看到的主要应用程序是在尝试不匹配元素时。但是,例如,这个来自最近一个问题的查询有一个简单的解决方案来捕获
*
,但是为什么要使用look back

(?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span
(?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span
(?
  • 您可以捕获重叠的匹配,并且可以找到可能位于其他匹配的查找区域中的匹配
  • 您可以表达有关匹配的复杂逻辑断言(因为许多引擎允许您使用多个lookback/lookahead断言,所有这些断言都必须匹配才能成功匹配)
  • Lookaround是一种表达公共约束“匹配X,如果后面跟/前面跟Y”的自然方式。添加额外的“匹配”部分(可以说)不太自然,这些部分必须通过后处理丢弃
  • 当然,负面环视断言更有用。与#2结合使用,它们可以让您完成一些漂亮的向导技巧,这在通常的程序逻辑中甚至很难表达


    例如,根据大众要求:

    • 重叠匹配:假设您希望找到给定基因序列中的所有候选基因。基因通常以ATG开头,以TAG、TAA或TGA结尾。但是,候选基因可能重叠:可能存在错误开始。因此,您可以使用如下正则表达式:

      ATG(?=((?:...)*(?:TAG|TAA|TGA)))
      
      <tr class="TableRow">.*?</tr>(?=<tr class="TableRow">|</table>)
      
      #ff00fffirstword#445533secondword##008877thi#rdword#
      
      这个简单的正则表达式寻找ATG起始密码子,然后是一些密码子,然后是一个终止密码子。它提取所有看起来像基因的东西(无起始密码子),并正确地输出基因,即使它们重叠

    • 零宽度匹配:假设您希望在计算机生成的HTML页面中查找每个具有特定类的
      tr

      ATG(?=((?:...)*(?:TAG|TAA|TGA)))
      
      <tr class="TableRow">.*?</tr>(?=<tr class="TableRow">|</table>)
      
      #ff00fffirstword#445533secondword##008877thi#rdword#
      

    有两件大事:

    • 它们是零宽度断言。它们需要匹配,但不消耗任何输入字符串。这允许描述匹配结果中不包含的字符串部分。通过在环视表达式中使用捕获组,它们是多次捕获部分输入的唯一方法
    • 它们简化了很多事情。它们很容易允许组合(相交)多个表达式以匹配字符串的同一部分

    请记住,正/负环顾与正则表达式引擎相同。环顾的目标是在“正则表达式”中的某个位置执行检查

    主要兴趣之一是在不使用捕获括号的情况下捕获某些内容(捕获整个模式),例如:

    字符串:
    aaabbbccc


    正则表达式:
    (?一个简单的例子是,当你将模式锚定到一行的开始或结束处,并且只想确保某个东西在你匹配的模式的正前方或正后方时,它们很方便。

    我试着解决你的问题:

    • 在我看来,查询中的某种环顾元素对于匹配的成功不是必需的

      当然,它们是匹配所必需的。只要环顾断言失败,就没有匹配。它们可用于确保模式周围的条件必须为真。整个正则表达式仅在以下情况下匹配:

    • 该图案确实适合

    • lookaround断言是正确的

    • ==>但是返回的匹配只是模式

    • 什么时候用积极的眼光看待周围才是真正更好的

      简单回答:当你想要东西在那里时,但你不想匹配它!

      因为它们是零宽度断言,这意味着它们不匹配字符序列,它们只是确保它在那里。因此环顾表达式中的字符不是“已使用”的,正则表达式引擎在最后一个“已使用”字符之后继续

    • 关于你的第一个例子:

      (?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span
      
      很有趣。它正在匹配一个数字序列(
      \d+
      ),在该序列之后,lookback断言将检查是否有一个前面有“id/”的数字。这意味着如果有多个数字或文本“id/”将失败数字丢失之前。表示此正则表达式仅匹配一个数字,而之前有匹配文本

    • 教学资源


    我假设你了解环顾四周的良好用途,并询问为什么在没有明显理由的情况下使用环顾四周

    我认为人们使用正则表达式的方式主要有四类:

    验证
    验证通常是在整个文本上进行的。不可能像您描述的那样进行环顾

    匹配
    提取部分文本。使用Lookarounds主要是因为开发人员懒惰:避免捕获。

    例如,如果我们在设置文件中有一行
    Index=5
    ,我们可以匹配
    /^Index=(\d+)/
    ,并获得第一个组,或者匹配
    /(?
    环顾断言
    也可以用于减少
    回溯
    ,这可能是正则表达式中性能差的主要原因

    例如:正则表达式
    ^[0-9A-Z]([-.\w]*[0-9A-Z])*@
    (1)也可以编写
    ^[0-9A-Z][-.\w]*(?查找断言)

    有关
    回溯的更多信息


    我前一段时间打了这封信,但很忙(仍然很忙,所以我可能需要一段时间才能回复),没有抽出时间发布。如果你仍然愿意接受答案


    是否有一些教学资源在推广它们

    我不这么认为,这是绝对的
    <td><a href="\/xxx\.html\?n=[0-9]{0,5}">(.*?)<\/a><span
    
    \bdog\b(?=(?:[^"]*"[^"]*")*[^"]*$)
    
    \bdog\b(?!(?:[^"]*"[^"]*")*[^"]*"[^"]*$)
    
    (?:"[^"]+"[^"]+?)?(\bdog\b)
    
    \bdog\b(?!(?:[^"]*"[^"]*")*[^"]*$)
    
    \bdog\b(?=(?:[^"]*"[^"]*")*[^"]*"[^"]*$)
    
    "[^"]*(\bdog\b)[^"]*"
    
    "[^"]*?(\bdog\b)[^"]*?(?:(\bdog\b)[^"]*?)?"
    
    abcdefghijkl
    
    (?=(...))
    
    1A Line1 Detail1 Detail2 Detail3 2A Line2 Detail 3A Line3 Detail Detail
    
    1A Line1 Detail1 Detail2 Detail3
    2A Line2 Detail
    3A Line3 Detail Detail
    
    [0-9]+A Line[0-9]+(?: \w+)+
    
    [0-9]+A Line[0-9]+(?: \w+)+?
    
    [0-9]+A Line[0-9]+(?: \w+)+?(?= [0-9]+A Line[0-9]+|$)
    
    #ff00fffirstword#445533secondword##008877thi#rdword#
    
    #ff00ff and firstword
    #445533 and secondword#
    #008877 and thi#rdword#
    
    (#[0-9a-f]{6})(.+?)(?=#[0-9a-f]{6}|$)
    
    ^(?=[^0-9]*[0-9])(?=[^a-z]*[a-z])
    
    ##-#
    #-##
    
    ^(?=.{4}$)\d+-\d+
    
    (?=.*(\b\w{3}\b))(?=.*(\b\d{4}\b)).*
    
    Oct-2013
    2013-Oct
    
    Oct-2013
    Oct-2013
    
    \G\d{1,2}\K\B(?=(?:\d{2})*\d{3}(?!\d))
    
       this    is  a   sentence    
    
    \s+
    
    ^\s*|\s$|\s+(?=\s)
    
    (?<=[0-9])(?=[A-Z])