2013-03-03 2 views
5

Эта картина:Сделать нежадным RegEx в обратном направлении, чтобы вести себя так же, как и в прямом направлении

/a+?b+?/ 

На следующей строке:

aaaaaabbbbbb 

соответствий:

aaaaaab 

Мы видим, что нежелательные ведут себя по-разному в обратном/левом направлении (принимает все) и в направлении вперед/вправо (занимает только один).

Есть ли способ сделать неживую в начале, которая соответствует всем a, чтобы соответствовать как можно меньше? Так что он ведет себя так же, как и с частью b в конце?

ответ

1

Они do ведут себя одинаково! Ленивый квантор (в этом случае ленивого +) говорит регулярное выражение двигателя до

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

Режимы не соответствуют «влево» или «назад», как вы, кажется, подразумеваете.

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

+0

Я хочу знать, общий способ, как получить как можно меньше матчей на левой стороне с 'Ā'. Да, конечно, это всего лишь пример. – flori

+1

Можете ли вы привести пример, который имеет смысл? Тогда можно было бы показать вам осмысленное решение. –

+0

@flori: Вам нужно как-то отклонить соответствие 'aaaaaab',' aaaaab', ... 'aab', чтобы соответствовать' ab', если это то, что вы хотите. В этом случае я бы пошел с 'indexOf (" ab ")'. – nhahtdh

2

Regexes обычно соответствуют слева направо, если вы не установили флаг справа налево (который поддерживает очень мало ароматов). В любом случае они не начинаются посередине, а затем работают в обоих направлениях, даже если вы используете lookbehind.

Это помогает остановиться и спросить - почему существует ленивый квантор? Какую проблему он хотел решить?

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

Например, рассмотрим следующий вход:

_abc_END_def_END 

И этот шаблон:

(\w+END)(\w+END)? 

Намерение, легко предположить, должен соответствовать _abc_, а затем END, а затем _def_ а затем END. Это выражение, по-видимому, допускает входы, где второй набор символов является необязательным.

Проблема состоит в том, что END является подмножеством \w+, поэтому второй набор фактически «съедается» \w+, что приводит к _abc_END_def_, совпадающим с последующим END. Это не желаемое поведение.

Решение этого сценария заключается в изменении способа поведения квантора с помощью ленивого модификатора. Это дает шаблон END шанс совпадения с каждым символом и позволяет только \w+ потреблять другой символ, если END терпит неудачу.

Цель ленивого квантификатора - не соответствовать «минимальному» числу символов - речь идет о том, чтобы дать второй образец, подмножество первого, возможность сопоставления.

В вашем примере b не является подмножеством a, поэтому нет необходимости в ленивом квантере. Если вы хотите, чтобы соответствовать один или больше, но как можно меньше, и один или несколько б, но как можно меньше, то вы бы просто использовать:

ab 

Или, если ваш a является стенд -в течение некоторого супермножестве, который может включать в себя B:

[ab]b 

Например:

\wb 

Оба из которых будет соответствовать:

ab 
1

Если вам не нужно выполнять предыдущее совпадение справа налево, вы можете просто изменить строку, отменить выражение регулярного выражения, а затем отменить результат в конце.

Работа заключается в следующем:

Start with aaaaaabbbbbb 
Reverse to bbbbbbaaaaaa 
Reverse /a+?b+?/ to /b+?a+?/ 
The resulting Match is bbbbbba 
Reverse the resulting match to get abbbbbb