Regex PHP соответствует только если не окружен котировками

У меня есть некоторое регулярное выражение, которое я просматриваю на всей HTML-странице, ищущей строки и заменяя их, однако, если строка находится в одинарных или двойных кавычках, я не хочу, чтобы она соответствовала.

Текущее Regex: ([a-zA-Z_][a-zA-Z0-9_]*)

Я хотел бы совместить steve, john, cathie и john 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

Ответ 1

Попробуйте следующее:

(\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

Ответ 2

Вы можете попробовать:

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

\w+ соответствует символам слов, но позволяет, например, 0123sophie. \b соответствует границам слов и, таким образом, гарантирует, что утверждения против кавычек не заканчиваются слишком рано.

Однако это регулярное выражение также не сможет найти слова, которые имеют только одну цитату "до или после".

Ответ 3

Для этого вам, вероятно, понадобится темная магия:

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

Часть (?:"[^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(?:\\\\.[^\'\\\\]*+)*+\') соответствует строке в одиночных или двойных кавычках и реализует обратную косую черту. (*SKIP)(*F) пропускает строку с кавычками и приводит к сбою. ([a-zA-Z_][a-zA-Z0-9_]*) - это ваше регулярное выражение.

PS: Если вы используете это на скриптах PHP, вы можете вместо этого использовать Tokenizer. Таким образом, вы могли бы, например, исключить ключевые слова (например, class или abstract, я не знаю, нужно ли вам это), и вам будет намного лучше обрабатывать граничные случаи (например, HEREDOC).

Ответ 4

Pez, воскрешая этот древний вопрос, потому что текущий ответ не совсем правильный (и я не уверен, что какое-либо решение может быть).

Он не будет соответствовать john, когда он находится в неполных кавычках, например, в "john, john", 'john и john' (ситуации, которые могут произойти с john birthday и т.д. См. эта демонстрация.

Это альтернативное решение просто пропускает любой контент в кавычках:

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

Смотрите демо

В любом случае, с кавычками, никакое решение не идеально, потому что вы всегда рискуете иметь несбалансированные кавычки. В этом случае я попытался смягчить проблему, предположив, что если она на другой строке, это другая строка.

Ссылка

Ответ 5

Хорошо, я думаю, что у меня есть это, и оно работает для ваших тестовых случаев:

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

Выполнен с функцией регулярного выражения look-ahead/look-behind.