#python #regex #regex-greedy #non-greedy
#python #Регулярное выражение #регулярное выражение-жадное #нежадный
Вопрос:
У меня есть файл «xml file», в котором есть несколько нежелательных символов
<data>
<tag>blar </tag><tagTwo> bo </tagTwo>
some extra
characters not enclosed that I want to remove
<anothertag>bbb</anothertag>
</data>
Я думал, что следующая нежадная замена удалит символы, которые не были должным образом заключены в <sometag></sometag>
re.sub("</([a-zA-Z] )>.*?<","</\1><",text)
^ ^ ^ ^ text is the xml txt.
remember tag, | | put tag back without and reopen next tag
read everything until the next '<' (non-gready)
Это регулярное выражение, похоже, находит только позицию, указанную с [[]]
помощью </tag>[[]]<tagTwo>
Что я делаю не так?
РЕДАКТИРОВАТЬ: мотивация для этого вопроса решена (см. Комментарии, у меня было отклонение amp; в файле xml, из-за которого он не анализировался — это не имело никакого отношения к символам, которые я хочу удалить). Тем не менее, мне все еще интересно, возможно ли регулярное выражение (и что было не так с моей попыткой), поэтому я не удаляю вопрос.
Комментарии:
1. @cwallenpoole: я не пытаюсь анализировать xml. Я пытаюсь очистить XML-файл, чтобы он мог быть принят синтаксическим анализатором. Любые предложения, отличные от регулярных выражений, относительно того, как это сделать, приветствуются
2. Какой анализатор это не принимает?
3. @IgnacioVazquez-Abrams
xml.dom.mindom
Я отредактировал вопрос, чтобы включить обратную трассировку4. Похоже, у вас там есть случайный амперсанд.
5. Ссылка на символьную сущность для амперсанда равна
amp;amp;
. Вы не можете просто выполнить глобальный S R, так как это может испортить другие действительные вещи.
Ответ №1:
Точка не соответствует новой строке, если вы не укажете re.DOTALL
флаг.
re.sub("</([a-zA-Z] )>.*?<","</\1><",text, flags=re.DOTALL)
должно работать нормально. (Если это не так, виноват мой python, а не регулярное выражение. Пожалуйста, исправьте.)
Я думаю, что хорошей практикой является быть как можно более точным при определении классов символов, которые должны повторяться. Это помогает предотвратить катастрофическое отслеживание возврата. Поэтому я бы использовал [^<]*
вместо .*?
с дополнительным бонусом, что теперь он находит случайные символы после последнего тега. Для этого больше не нужен re.DOTALL
флаг, поскольку [^<]
он соответствует новым строкам.
Ответ №2:
"</[^>] ?>[^<>] ?<"
в ipython:
In [1]: a="<data> <tag>blar </tag><tagTwo> bo </tagTwo> some extra characters not enclosed that I want to remove <anothertag>bbb</anothertag></data>"
In [2]: import re
In [3]: re.sub( "(</[^>] ?>)[^<>] ?<" ,"\1<",a)
Out[3]: '<data> <tag>blar </tag><tagTwo> bo </tagTwo><anothertag>bbb</anothertag></data>'