Интересно, в чем проблема с backreference здесь:
preg_match_all('/__\((\'|")([^\1]+)\1/', "__('match this') . 'not this'", $matches);
он должен соответствовать строке между __ (''), но на самом деле он возвращает:
match this') . 'not this
есть идеи?
Сделайте свое регулярное выражение неровным:
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')
и его лучше использовать ('[^']*'|"[^"]*)
как
Вы можете использовать что-то вроде: /__\(("[^"]+"|'[^']+')\)/