regex, проблема с backreference в шаблоне с preg_match_all

Интересно, в чем проблема с backreference здесь:

preg_match_all('/__\((\'|")([^\1]+)\1/', "__('match this') . 'not this'", $matches); 

он должен соответствовать строке между __ (''), но на самом деле он возвращает:

 match this') . 'not this 

есть идеи?

Solutions Collecting From Web of "regex, проблема с backreference в шаблоне с preg_match_all"

Сделайте свое регулярное выражение неровным:

 preg_match_all('/__((\'|")([^\1]+)\1/U', "__('match this') . 'not this'", $matches) 

Вы не можете использовать backreference внутри класса символов, потому что класс символов соответствует ровно одному символу, а обратная ссылка может потенциально соответствовать любому количеству символов или никому.

То, что вы пытаетесь сделать, требует негативного взгляда, а не отрицательного символьного класса:

 preg_match_all('/__\(([\'"])(?:(?!\1).)+\1\)/', "__('match this') . 'not this'", $matches); 

Я также изменил ваше чередование – \'|" – на класс символов – [\'"] – потому что он намного эффективнее, и я избежал внешних круглых скобок, чтобы они соответствовали буквальным круглым скобкам.


EDIT: Я думаю, мне нужно расширить это «более эффективное» замечание. Я привел пример, который Фридл использовал для демонстрации этого момента и протестировал его в RegexBuddy.

Применительно к целевому тексту abababdedfg ,
^[ag]+$ сообщает успех после трех шагов, тогда как
^(?:a|b|c|d|e|f|g)+$ принимает 55 шагов.

И это для успешного матча. Когда я пробую это на abababdedfz ,
^[ag]+$ сообщает о сбое после 21 шага;
^(?:a|b|c|d|e|f|g)+$ принимает 99 шагов.

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

Я удивлен, что он не дал вам сообщение об ошибке в случае дисбаланса.

  / __ ( (\'|") ([^\1]+) \1 / 

Этот [^\1] не будет принимать содержимое буфера захвата 1 и помещать его в символ
класс. Это то же самое, что и все символы, которые НЕ '1'.

Попробуй это:

/__\(('|").*?\1\).*/

Вы можете добавить внутреннюю скользящую скобку, чтобы просто зафиксировать, что между кавычками:
/__\(('|")(.*?)\1\).*/

Изменить: если внутренний интервал не разрешен, используйте регулярное выражение Qtax.
Поскольку, ('|").*?\1 хотя и не жадный, по-прежнему будет соответствовать всем __('all'this'will"match') . В этом случае __('all'this'will"match') и его лучше использовать ('[^']*'|"[^"]*) как

Вы можете использовать что-то вроде: /__\(("[^"]+"|'[^']+')\)/