Python 非贪婪正则表达式清理 XML

2 投票
2 回答
1181 浏览
提问于 2025-04-17 03:46

我有一个“xml文件”,里面有一些不想要的字符。

<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>中用[[]]表示的位置。我哪里做错了呢?

编辑: 问这个问题的原因已经解决了(见评论,我的xml文件里有一个多余的&符号,导致它无法解析——这和我想删除的字符没有关系)。不过,我还是想知道这个正则表达式是否可行(以及我尝试时哪里出错),所以我没有删掉这个问题。

2 个回答

1
 "</[^>]+?>[^<>]+?<" 
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>'

在ipython中:

3

点号在正则表达式中默认是不能匹配换行符的,除非你加上 re.DOTALL 这个标志。

re.sub("</([a-zA-Z]+)>.*?<","</\\1><",text, flags=re.DOTALL)

这样应该没问题。(如果不行,那就是我的 Python 有问题,不是正则表达式的问题,请纠正我。)

我觉得在定义要重复的字符类时,尽量精确是个好习惯。这可以帮助避免出现 灾难性的回溯。所以,我会用 [^<]* 来代替 .*?,这样还可以找到最后一个标签后面的多余字符。这样就不需要再加 re.DOTALL 这个标志了,因为 [^<] 是可以匹配换行符的。

撰写回答