正则表达式PHP仅匹配,如果没有被行情包围

时间:2011-03-04 17:51:20

标签: php regex

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

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

我想匹配stevejohncathiejohn 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

5 个答案:

答案 0 :(得分:3)

试试这个:

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

反对这个字符串:

john "michael" michael 'michael elt0n_john 'elt0n_j0hn'
 1      2        3        4       5            6

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

答案 1 :(得分:2)

您可以尝试:

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

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

然而,这个正则表达式也无法找到只有一个单引号“之前或之后”的单词。

答案 2 :(得分:1)

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

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

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

PS:如果您在PHP脚本上使用此功能,则可能需要使用Tokenizer。这样你就可以排除关键字(例如classabstract,我不知道你是否需要这个),你可以更好地处理边缘情况(比如HEREDOC)。

答案 3 :(得分:1)

佩斯,复活这个古老的问题,因为目前的答案不太正确(我不确定任何解决方案都可以)。

如果john位于不完整的引号中,则无法与"john匹配,例如john"'johnjohn'john's birthday(可以是(?:'[^'\n]*'|"[^"\n]*")(*SKIP)(*F)|\b[a-zA-Z_][a-zA-Z_0-9]*\b 与{{1}}等同时发生。请参阅this demo

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

{{1}}

请参阅demo

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

参考

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

答案 4 :(得分:0)

好的我觉得我有它,它适用于你的测试用例:

(?<!"|'|\w)(\w+)(?!"|'|\w)

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