5

У меня есть следующее регулярное выражение на двух разных языках, которое производит те же нечетные результаты (javaScript и Flash). То, что я хочу знать, это не то, как это исправить, но почему такое поведение происходит?Regex только фиксирует последний экземпляр группы захвата в матче

Регулярное выражение:

\[(\\{2}|\\\]|[^\]])*\] 

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

Если у меня есть ввод текста [abcdefg], он правильно подобран, но единственное, что возвращается как часть группы захвата, это g, где, как я ожидаю, abcdefg. Если я сменил выражение на \[((?:\\{2}|\\\]|[^\]])*)\], тогда я получу результат, который я хочу.

Так почему же это происходит? Будет ли это соответствовать другим языкам?

примечание: Упрощение выражения до \[([^\]])*\] дает ту же проблему.

ответ

7

Независимо от проблемы, ActionScript и JavaScript должен всегда давать те же результаты, как они оба реализации ECMAScript (или надстройкой их, но для регулярных выражений они не должны противоречить).

Но да, это будет происходить на любом языке (или, скорее, на любом регулярном выражении). Причина в том, что вы повторяете группу захвата. Давайте рассмотрим более простой пример: соответствие (.)* против abc. Так что мы повторяем (.). В первый раз, когда он пробуется, двигатель входит в группу, соответствует a с ., покидает группу и захватывает a. Только теперь квантификатор вступает, и он повторяет все это. Итак, мы снова входим в группу и сопоставляем и фиксируем b. Этот захват перезаписывает предыдущий, поэтому \1 теперь содержит b. То же самое для третьего повторения: захват будет перезаписан с помощью c.

Я не знаю о регулярном выражении, который ведет себя по-другому, и единственный, который позволяет вам получить доступ ко всем предыдущим захватам (а не просто переписывать их), - это .NET.

Решение является одним p.s.w.g. предложенный. Сделайте группировку, которая вам нужна для повторной записи, не захватывающей (это улучшит производительность, потому что вам не нужно все, что захватывает и перезаписывает) и обернуть все это в новую группу. У вашего выражения есть один маленький недостаток, хотя: вы должны включить включить обратную косую черту в отрицательном классе символов. В противном случае откат может дать вам матч в [abc\]. Так вот это выражение, которое будет работать, как вы ожидаете:

\[((?:\\{2}|\\\]|[^\]\\])*)\] 

Working demo. (к сожалению, она не показывает снимки, но это показывает, что она дает правильные матчи во всех случаях)

Обратите внимание, что выражение не допускает других управляющих последовательностей. В частности, один \, за которым следует всего, но ], приведет к сбою вашего шаблона.Если это не то, что вы хотите, вы можете просто использовать:

\[((?:\\.|[^\]\\])*)\] 

Working demo.

Производительность может быть дополнительно улучшена с помощью "unrolling-the-loop" техники:

\[([^\]\\]*(?:\\.[^\]\\]*)*)\] 

Working demo.

2

Try включая * квантора внутри группы захвата, как это:

\[((?:\\{2}|\\\]|[^\]])*)\]