【问题标题】:Regex PHP Only Match if Not Surrounded By Quotes正则表达式 PHP 仅在没有被引号包围时匹配
【发布时间】:2014-05-15 09:50:22
【问题描述】:

我有一些正则表达式,我在整个 HTML 页面上运行以查找字符串并替换它们,但是如果字符串是单引号或双引号,我不希望它匹配。

当前正则表达式:([a-zA-Z_][a-zA-Z0-9_]*)

我想匹配 steve,john,cathiejohn likes to walk (x3) 但不是"steve"'sophie'"john"'likes'"cake"

我尝试了(^")([a-zA-Z_][a-zA-Z0-9_]*)(^"),但没有找到匹配项?

测试用例:

(steve=="john") would return steve
("test"=="test") would not return anything
(boob==lol==cake) would return all three

【问题讨论】:

  • 我再次查看了您的正则表达式,发现 ([a-zA-Z_][a-zA-Z0-9_]*) 已经匹配而没有引号...
  • @BoltClock 问题是他只希望它在没有引号时匹配(我认为)。
  • 这些字符串是原样吗?开始/结束是stevejohn。或者它们是否存在于另一个上下文中,例如steve went for a walk with john. John said "Steve"。什么是几个测试用例?
  • 上下文是什么...请测试用例...

标签: php regex


【解决方案1】:

试试这个:

(\b(?<!['"])[a-zA-Z_][a-zA-Z_0-9]*\b(?!['"]))

针对这个字符串:

约翰“迈克尔”迈克尔“迈克尔 elt0n_john 'elt0n_j0hn' 1 2 3 4 5 6

它将匹配 nr 1 john、nr 3 Michael 和 nr 5 elt0n_john

【讨论】:

    【解决方案2】:

    要做到这一点,你可能需要一些黑魔法:

    '~(?:"[^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(?:\\\\.[^\'\\\\]*+)*+\')(*SKIP)(*F)|([a-zA-Z_][a-zA-Z0-9_]*)~'
    

    (?:"[^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(?:\\\\.[^\'\\\\]*+)*+\') 部分匹配单引号或双引号中的字符串,并实现反斜杠转义。 (*SKIP)(*F) 跳过引用的字符串并强制失败。 ([a-zA-Z_][a-zA-Z0-9_]*) 是你的正则表达式。

    PS:如果您在 PHP 脚本上使用它,您可能希望使用 Tokenizer 代替。这样您就可以排除关键字(例如 classabstract,我不知道您是否需要这个),并且您将更好地处理边缘情况(例如 HEREDOC)。

    【讨论】:

      【解决方案3】:

      你可以试试:

      preg_match_all('#(?<!["\']) \b \w+ \b (?!["\'])#x', $str, $matches);
      

      \w+ 匹配单词字符,但例如允许0123sophie\b 匹配单词边界,从而确保反引用断言不会过早终止。

      但是,此正则表达式也将无法找到只有一个单引号“在它们之前或之后”的单词。

      【讨论】:

      • 在正则表达式教练中经过测试并且效果很好......虽然在 PHP 中失败,但不知道为什么。 codepad.org/LEitQoEJ 可能只是键盘的问题。
      • 也做了同样的事情。使用我在 PHP CLI 中尝试过的 codpad 中发布的测试用例。它工作得很好,并返回一个包含butjohnlikeapples的数组
      【解决方案4】:

      Pez,复活这个古老的问题,因为当前的答案并不完全正确(我不确定任何解决方案都可以)。

      john 包含在不完整的引号中时,它将无法匹配,例如"johnjohn"'johnjohn'john's birthday 等可能发生的情况。请参阅@987654321 @。

      此替代解决方案只是跳过引号中的任何内容:

      (?:'[^'\n]*'|"[^"\n]*")(*SKIP)(*F)|\b[a-zA-Z_][a-zA-Z_0-9]*\b
      

      demo

      无论哪种方式,使用引号都没有完美的解决方案,因为您总是冒着引号不平衡的风险。在这种情况下,我试图通过假设如果它在另一行,它是一个不同的字符串来缓解这个问题。

      参考

      1. How to match pattern except in situations s1, s2, s3
      2. How to match a pattern unless...

      【讨论】:

        【解决方案5】:

        好的,我想我知道了,它适用于您的测试用例:

        (?

        使用前瞻/后瞻正则表达式功能完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-11
          • 1970-01-01
          • 1970-01-01
          • 2021-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多