2015-03-13 4 views
0

Я пытаюсь захватить текст между двумя ближайшими фразами, включая эти фразы, но отрицательный взгляд не работает в моей ситуации.Regex Negative Lookahead не работает должным образом

Таким образом, это является частью текстового файла:

<in><il>plural</il> <if>aba*cus*es</if> <il>also</il> <if>aba*ci</if> <sound><wav>abaci001.wav</wav><wav>abaci002.wav</wav></sound> <pr>-ˌsaɪ</pr> <altpr>ˈæbəˌsaɪ</altpr></in> 
<in><il>plural</il> <if>fau*nas</if> <il>also</il> <if>fau*nae</if> <sound><wav>fauna002.wav</wav></sound> <pr>ˈfɑ:ˌni:</pr></in> 
<il>or</il> <if>fur*ther</if> <sound><wav>far00003.wav</wav></sound> <in><if>far*thest</if> <sound><wav>farthe03.wav</wav></sound> 

мне нужно, чтобы захватить каждую пару <if>...</if> и <wav>...</wav> тегов.

Мои регулярные выражения: <if>.*?<\/if>(?:(?!<if>.*?<\/if>).)*?<wav>.*?<\/wav>

Regex101 Пример: https://regex101.com/r/eT4wJ9/1

По какой-то причине, если вы два или более вхождений <if>...</if> тега, это регулярное выражение соответствует всем, начиная с первого появления несмотря отрицательного предпросмотра , Почему это происходит?

+0

Вы не должны пытаться обработать XML с помощью регулярных выражений. Есть несколько модулей Perl в CPAN, которые работают очень хорошо (например, 'XML :: Twig' или' XML :: LibXML', но * не используют 'XML :: Simple') и делают эту задачу очень простой, а также обеспечение проверенного и гораздо более надежного решения. Вы никогда не будете уверены, что небольшое изменение XML-данных, которые вы не пробовали тестировать, не нарушит реализацию вашего регулярного выражения. – Borodin

+0

Да, я знаю, что регулярное выражение не лучший инструмент для анализа HTML или XML, но это одноразовая задача, поэтому я решил попробовать. – Systematis

+0

Не понимаю. Почему выбрать неправильный инструмент только потому, что это одноразовая задача? Вы говорите: «Я только поеду в близлежащие магазины, так что возьму газонокосилку» – Borodin

ответ

1

Вам также нужно добавить отрицательный lookahead в блок if, чтобы он не соответствовал вложенным тегам if.

<if>(?:(?!</?if>).)*<\/if>(?:(?!<if>.*?<\/if>).)*?<wav>(?:(?!</?wav>).)*<\/wav> 

DEMO

Пример:

>>> s = '''<in><il>plural</il> <if>aba*cus*es</if> <il>also</il> <if>aba*ci</if> <sound><wav>abaci001.wav</wav><wav>abaci002.wav</wav></sound> <pr>-ˌsaɪ</pr> <altpr>ˈæbəˌsaɪ</altpr></in> 
<in><il>plural</il> <if>fau*nas</if> <il>also</il> <if>fau*nae</if> <sound><wav>fauna002.wav</wav></sound> <pr>ˈfɑ:ˌni:</pr></in> 
<il>or</il> <if>fur*ther</if> <sound><wav>far00003.wav</wav></sound> <in><if>far*thest</if> <sound><wav>farthe03.wav</wav></sound>''' 
>>> for i in re.findall(r'<if>(?:(?!</?if>).)*<\/if>(?:(?!<if>.*?<\/if>).)*?<wav>(?:(?!</?wav>).)*<\/wav>', s): 
     print(i) 


<if>aba*ci</if> <sound><wav>abaci001.wav</wav> 
<if>fau*nae</if> <sound><wav>fauna002.wav</wav> 
<if>fur*ther</if> <sound><wav>far00003.wav</wav> 
<if>far*thest</if> <sound><wav>farthe03.wav</wav> 
+1

'. *? <\/if>' лишний – Borodin

+0

Отлично работает. Спасибо, Авинаш Радж. – Systematis

Смежные вопросы