2013-10-06 3 views
0

Скажем, у меня есть тег <tag> и я хочу сопоставить группы <tag>...<tag> в моей строке. Я могу использовать регулярное выражение по строкам <tag>.*<tag>. Это соответствует <tag>foo<tag>, что хорошо, но оно также соответствует <tag>foo<tag>bar<tag>, что поведению я не хочу. Я хочу, чтобы <tag>foo<tag> был сопоставлен, затем следует исключить bar, а затем тег на конце станет началом следующего матча. Как мне это сделать?Ruby Regular Expression - предотвращает совпадение совпадений

+0

У вас есть HTML-строка? –

+0

Это не обязательно HTML - '' может быть заменено на любую последовательность. – Kvass

+0

Любая повторяющаяся последовательность будет быстро показывать недостаток использования регулярных выражений, и ваша задача придумать шаблон, который позволяет избежать столкновений/перекрытий, будет ракетой. * ЕСЛИ * вы работаете с HTML или XML, не беспокойтесь о регулярном выражении, если ваши потребности являются чем-то большим, чем наименее тривиальное использование. Вместо этого используйте парсер, например, Nokogiri. Ваш мозг поблагодарит вас позже. –

ответ

4

Самым простым решением является использование ленивого quantifier где ? вынуждает .*, чтобы соответствовать как несколько символов, насколько это возможно (и не как много как можно, как неукрашенной .* будет пытаться соответствовать):

<tag>.*?<tag> 

более безопасный, более явное решение заключается в использовании negative lookahead assertion:

<tag>(?:(?!<tag>).)*<tag> 

В то время как в данном случае, нет никакой разницы в поведении, то второй из них является расширяемой для обработки открытия/закрытия тегов, убедившись, что вложенные теги не неправильно подобраны:

<tag>(?:(?!</?tag>).)*</tag> 

применительно к <tag>foo<tag>bar</tag>baz</tag> будет совпадение <tag>bar</tag>, а не <tag>foo<tag>bar</tag> как решение с ленивым квантором.

+2

Можете ли вы объяснить, что делает его «более безопасным»? – Kvass

2

Вы можете использовать ленивую версию .* существ:

<tag>.*?<tag> 
    ^

? делает .* матч до до первого матча <tag>.

+0

Я не уверен, что буду следовать - не будет '?' Просто избыточным, так как '. *' Означает ноль или более любого символа? – Kvass

+0

@Kvass Здесь '?' Действует как «модификатор», а не «0 или 1 раз». '. *?' называется «ленивым», а '. *' считается «жадным». – Jerry