Захватить последнее вхождение тега - PullRequest
0 голосов
/ 24 июня 2010

Мой текст имеет вид:

<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 ]

3 голосов
/ 24 июня 2010

Это тот же код, который создает весь файл - если это так, тогда используйте для создания его библиотеку xml, тогда все теги будут правильно вложены - если не исправить код, создающий его, чтобы он был действительным XML.

регулярные выражения и xml плохо сочетаются.

1 голос
/ 24 июня 2010

Вы действительно должны использовать такой синтаксический анализатор, как BeautifulSoup , чтобы выполнить эту работу.BeautifulSoup может анализировать очень неправильный HTML / XML и пытается заставить их выглядеть правильно.Ваш код может выглядеть следующим образом (я предполагаю, что у вас есть несколько тегов до и после неверного тега Story, иначе вы бы следовали совету из комментария Дэвида):

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)

Посмотрите, как анализировалась BeautifulSoupit:

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 прямо перед закрытием тега, который его окружал (Document), поэтому вам нужно переместить закрывающий тег рядом с последним предложением.

# 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>

Конечный результат должен быть именно тем, что вы хотели.Обратите внимание, что в этом коде предполагается, что в документе есть только одна история, в противном случае ее следует слегка изменить.Удачи!

0 голосов
/ 25 июня 2010

Почему бы не сопоставить все три (или сколько угодно) элемента <Sentence> и снова подключить их к групповой ссылке?

re.sub(r'(?:(\r?\n) *<Sentence.*?</Sentence> *)+',
       r'$0$1</Story>',
       line)
0 голосов
/ 25 июня 2010

Если вам нужно только найти последнее вхождение тега, вы можете:

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
...