【问题标题】:How find every thing but not one word如何找到每一件事,但没有一个词
【发布时间】:2011-12-19 16:36:35
【问题描述】:

在文本中,我想找到像每件事一样的结构,直到某些文本,但在某些单词之间不匹配。

文本示例:

Templates : You can add custom templates for your theme. Updated on 2010 look[124] end
Media RSS feed : Add the Cooliris Effect to your gallery Updated on 2011 look[124]
Role settings : Each gallery has a author Updated at 2010 ...  look[124] end
AJAX based thumbnail generator : No more server Updated on 2010 look[124] end limitation during the batch process Copy/Move : Copy or move images between Updated on 2010 this look[124] galleries Sortable Albums : Create your own sets of images Updated on 2010 this look[124] end
Upload or pictures via a zip-file (Not in Safe-mode)
Watermark function : You can add a watermark image or text 
...

我需要找到 "Updated .*[124] end" 每场比赛都必须开始这个 "Update" 并以 "[number]" 和单词 "end 结尾”。但有些文本看起来非常相似,但 not 以单词“end”结尾。此文本必须不匹配。如何让它发挥作用?

我试着写

/Updated(.*?)\[.*?\]\send/msi

Updated(.*?)\[.*?\](?!Updated)\send

但这需要像这样的字符串:

Updated on 2011 look[124] Role settings : Each gallery has a author Updated at 2010 ...  look[124] end
Updated on 2010 this look[124] galleries Sortable Albums : Create your own sets of images Updated on 2010 this look[124] end

如何编写正则表达式女巫跳过糟糕的匹配?

http://regexr.com?2vh1j

感谢您的意见。

【问题讨论】:

  • 而且,请记住,正则表达式是贪婪的,它们会尝试匹配一行中最长的东西

标签: php regex preg-match


【解决方案1】:

我认为这是您尝试使用第二个正则表达式的目的:

Updated\s++(?>(?!Updated\b|end\b)\S+\s+)*+end\b

换句话说,匹配Updated 并查找对应的end。如果你先找到另一个Updated,你就知道你从错误的地方开始,所以放弃那场比赛。我也排除了end,因为这让我可以所有格匹配这些词(即,与*+);正则表达式永远不必回溯以查找或(更重要的是)消除匹配项。

如果你真的必须指定 look[nnn] 部分,这应该可以解决问题:

Updated\s++(?>(?!Updated\b|end\b|look\[\d+\])\S+\s+)*+look\[\d+\]\s+end\b

如果需要,添加 i 标志以进行不区分大小写的匹配,但不需要 ms 标志。如果这看起来过于复杂,那是因为我不像你那样了解你的数据。很有可能这就是你真正需要的:

Updated(?:(?!Updated).)*\send

【讨论】:

    【解决方案2】:

    假设所有无效匹配都有[124],但没有end,您可以通过在Updated 和结束序列之间不允许[ 来过滤掉它们,如下所示:

    Updated([^[]*?)\[\d*\]\send
    

    【讨论】:

      【解决方案3】:

      要匹配不包含 Updated 的字符串,您可以使用如下结构:

      (?:[^U]+|U(?!pdated))*
      

      (?:(?!Updated).)*
      

      使用第一个选项会给你一个类似的表达式:

      Updated((?:[^U]+|U(?!pdated))*)\[\d+\]\send
      

      解释第一个替代方案:

      (?:          # non-capturing group
      [^U]+        # any characters that aren't "U"
      |U(?!pdated) # or a "U" which is not followed bu "pdated" (ie. not "Updated")
      )*           # repeated as much as possible
      

      第二种选择:

      (?:          # non-capturing group
      (?!Updated). # Use a lookahead check at every character to make sure it's not "Updated"
      )*           # repeated as much as possible
      

      【讨论】:

      • +1,我肯定会采用第二种方法。第一个可能会更快,但不会快很多。无论如何,不​​足以证明可读性受到影响。请参阅我对性能恋物癖者方法的回答。 ;)
      【解决方案4】:

      使用惰性正则表达式

      Updated.*?\[.*?\]( end)?
      

      【讨论】:

        【解决方案5】:

        一种可能性:

        Updated([^[]*)\[124\]\s+end
        

        解释:

        Updated          # Word 'updated'
        [^[]*            # All chars until '['
        \[124\]          # String '[124]'
        \s+              # One or more spaces.
        end              # String 'end'
        

        【讨论】:

          【解决方案6】:

          也许你可以尝试不同的方法:

          /Updated[\w.\s]*\[\d+\]\send/
          

          说明:

          Updated
          

          这将匹配单词Updated

          [\w\d.\s]*
          

          然后是所有字母、数字、空格和点(你可以添加任何你想要的字符)

          \[\d+\]
          

          然后是括号之间的数字

          \send
          

          比一个空格最后是单词结尾

          【讨论】:

          • 我认为你的意思不是(\w*\d*\.*\s*)*,而是[\w.\s]*
          猜你喜欢
          • 2021-04-24
          • 2010-12-22
          • 2018-11-12
          • 1970-01-01
          • 1970-01-01
          • 2015-05-17
          • 1970-01-01
          • 1970-01-01
          • 2020-01-23
          相关资源
          最近更新 更多