捕获最后一次出现的标记

时间:2010-06-24 06:12:50

标签: python xml regex last-occurrence

我的文字形式如下:

<Story>
 <Sentence id="1"> some text </Sentence>   
 <Sentence id="2"> some text </Sentence>   
 <Sentence id="3"> some text </Sentence>   

我的任务是在最后</Story>之后插入结束标记</Sentence>。在文中,每个</Sentence>后跟3个空格。我尝试使用正则表达式</Sentence>捕获最后一个</Sentence>(?!.*<Sentence)并使用了re.DOTALL。但它不起作用。

使用的实际代码是
line = re.sub(re.compile('</Sentence>(?!.*<Sentence)',re.DOTALL),'</Sentence></Story>',line)

请帮忙。感谢。

4 个答案:

答案 0 :(得分:3)

生成整个文件的代码是否相同 - 如果是这样,那么使用xml库生成它然后所有标记都将正确嵌套 - 如果不修复生成它的代码,那么它就是有效的XML。

正则表达式和xml不能很好地结合在一起。

答案 1 :(得分:1)

你真的应该使用像BeautifulSoup这样的解析器来完成这项工作。 BeautifulSoup可以解析非常不正确的HTML / XML并尝试使它们看起来正确。您的代码看起来像这样(我假设您在错误的Story标记之前和之后都有一些标记,否则您将遵循David的评论中的建议):

from BeautifulSoup import BeautifulStoneSoup

html = '''
<Document>
<PrevTag></PrevTag>
<Story>
 <Sentence id="1"> some text </Sentence>   
 <Sentence id="2"> some text </Sentence>   
 <Sentence id="3"> some text </Sentence>
<EndTag></EndTag>
</Document> 
'''
# Parse the document:
soup = BeautifulStoneSoup(html)

看看BeautifulSoup如何解析它:

print soup.prettify()

#<document>
# <prevtag>
# </prevtag>
# <story>
#  <sentence id="1">
#   some text
#  </sentence>
#  <sentence id="2">
#   some text
#  </sentence>
#  <sentence id="3">
#   some text
#  </sentence>
#  <endtag>
#  </endtag>
# </story>
#</document>

请注意,BeautifulSoup在关闭包围它的标记(文档)之前关闭了Story,所以你必须在最后一句旁边移动结束标记。

# Find the last sentence:
last_sentence = soup.findAll('sentence')[-1]

# Find the Story tag:
story = soup.find('story')

# Move all tags after the last sentence outside the Story tag:
sib = last_sentence.nextSibling
while sib:
    story.parent.append(sib.extract())
    sib = last_sentence.nextSibling

print soup.prettify()

#<document>
# <prevtag>
# </prevtag>
# <story>
#  <sentence id="1">
#   some text
#  </sentence>
#  <sentence id="2">
#   some text
#  </sentence>
#  <sentence id="3">
#   some text
#  </sentence>
# </story>
# <endtag>
# </endtag>
#</document>

最终结果应该是您想要的。请注意,此代码假定文档中只有一个故事 - 如果没有,则应略微修改。祝你好运!

答案 2 :(得分:0)

如果你只需找到标签的最后一次出现,你可以:

reSentenceClose= re.compile('</Sentence> *')
match= None
for match in reSentenceClose.finditer(your_text):
    pass

if match: # it was found
    print match.end() # the index in your_text where the pattern was found

答案 3 :(得分:0)

为什么不匹配所有三个(或多个)<Sentence>元素并使用组引用将其重新插入?

re.sub(r'(?:(\r?\n) *<Sentence.*?</Sentence> *)+',
       r'$0$1</Story>',
       line)