Python: чтение части текстового файла - PullRequest
4 голосов
/ 08 июня 2009

Привет все

Я новичок в питоне и программировании. Мне нужно читать кусками большого текстового файла, формат выглядит следующим образом:

<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>

Мне нужна информация form, lemma и postag. например для вышеупомянутых мне нужно hibernis, hibernus1 и n-p---nb-.

Как мне сказать python читать, пока он не достигнет формы, прочитать вперед, пока он не достигнет кавычки ", а затем прочитать информацию между кавычками "hibernis"? Действительно борется с этим.

До сих пор я пытался убрать пунктуацию, разбить предложение и затем извлечь нужную информацию из списка. Хотя у меня проблемы с получением Python для перебора всего файла, я могу заставить это работать только для 1 строки. Мой код ниже:

f=open('blank.txt','r')
quotes=f.read()
noquotes=quotes.replace('"','')
f.close()

rf=open('blank.txt','w')
rf.write(noquotes)
rf.close()   

f=open('blank.txt','r')
finished = False
postag=[]
while not finished:
   line=f.readline()
   words=line.split()
   postag.append(words[4])
   postag.append(words[6])
   postag.append(words[8])              
   finished=True

Буду признателен за любые отзывы / критику

спасибо

Ответы [ 9 ]

5 голосов
/ 08 июня 2009

Если это XML, используйте ElementTree для его анализа:

from xml.etree import ElementTree

line = '<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>'

element = ElementTree.fromstring(line)

Для каждого элемента XML вы можете легко извлечь имя и все атрибуты:

>>> element.tag
'word'
>>> element.attrib
{'head': '7', 'form': 'hibernis', 'postag': 'n-p---nb-', 'lemma': 'hibernus1', 'relation': 'ADV', 'id': '8'}

Так что, если у вас есть документ с кучей word элементов XML, что-то вроде этого извлечет информацию, которую вы хотите из каждого:

from xml.etree import ElementTree

XML = '''
<words>
    <word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>
</words>'''

root = ElementTree.fromstring(XML)

for element in root.findall('word'):
    form = element.attrib['form']
    lemma = element.attrib['lemma']
    postag = element.attrib['postag']

    print form, lemma, postag

Используйте parse() вместо fromstring(), если у вас есть только имя файла.

2 голосов
/ 08 июня 2009

Я бы предложил использовать модуль регулярных выражений: re

Возможно, что-то в этом роде?

#!/usr/bin/python
import re

if __name__ == '__main__':
    data = open('x').read()
    RE = re.compile('.*form="(.*)" lemma="(.*)" postag="(.*?)"', re.M)
    matches = RE.findall(data)
    for m in matches:
        print m

Это предполагает, что каждая строка <word ...> находится на одной строке, и что каждая часть находится в этом точном порядке, и что вам не нужно иметь дело с полным разбором xml.

1 голос
/ 08 июня 2009

В дополнение к обычному ответу RegEx, поскольку это выглядит как форма XML, вы можете попробовать что-то вроде BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/)

Это очень легко использовать и находить теги / атрибуты в таких вещах, как HTML / XML, даже если они не «хорошо сформированы». Может стоит посмотреть.

1 голос
/ 08 июня 2009

Является ли ваш файл правильным XML? Если так, попробуйте парсер SAX:

import xml.sax
class Handler (xml.sax.ContentHandler):
   def startElement (self, tag, attrs):
       if tag == 'word':
           print 'form=', attrs['form']
           print 'lemma=',attrs['lemma']
           print 'postag=',attrs['postag']

ch = Handler ()
f = open ('myfile')
xml.sax.parse (f, ch)

(это грубо ... это может быть не совсем правильно).

0 голосов
/ 08 июня 2009

ух ты, ребята, быстро :) Если вам нужны все атрибуты списка (а порядок известен), вы можете использовать что-то вроде этого:

import re
print re.findall('"(.+?)"',INPUT)

INPUT - это строка типа:

<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>

и печатный список:

['8', 'hibernis', 'hibernus1', 'n-p---nb-', '7', 'ADV']
0 голосов
/ 08 июня 2009

Во-первых, не тратьте много времени на переписывание файла. Обычно это пустая трата времени. Обработка для очистки и синтаксического анализа тегов настолько быстрая, что вы будете совершенно счастливы, работая с исходным файлом все время.

source= open( "blank.txt", "r" )
for line in source:
    # line has a tag-line structure
    # <word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>
    # Assumption -- no spaces in the quoted strings.
    parts = line.split()
    # parts is [ '<word', 'id="8"', 'form="hibernis"', ... ]
    assert parts[0] == "<word"
    nameValueList = [ part.partition('=') for part in parts[1:] ]
    # nameValueList is [ ('id','=','"8"'), ('form','=','"hibernis"'), ... ]
    attrs = dict( (n,eval(v)) for n, _, v in nameValueList )
    # attrs is { 'id':'8', 'form':'hibernis', ... }
    print attrs['form'], attrs['lemma'], attrs['posttag']
0 голосов
/ 08 июня 2009

С регулярными выражениями это суть (вы можете сделать часть file.readline ()):

import re
line = '<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>'
r = re.compile( 'form="([^"]*)".*lemma="([^"]*)".*postag="([^"]*)"' )
match = r.search( line )
print match.groups()

>>> 
('hibernis', 'hibernus1', 'n-p---nb-')
>>> 
0 голосов
/ 08 июня 2009

Просто чтобы подчеркнуть вашу проблему:

finished = False
counter = 0
while not finished:
   counter += 1
   finished=True
print counter
0 голосов
/ 08 июня 2009

Разбор XML вручную - это обычно неправильная вещь Во-первых, ваш код сломается, если сбежал цитата в любом из атрибутов. Получение атрибутов из XML парсер наверное чище и меньше подверженные ошибки.

Подобный подход также может столкнуться с проблемами при разборе всего файла, если у вас есть строки, которые не соответствуют формату. Вы можете справиться с этим, создав метод parseline (что-то вроде

def parse (line):
      try: 
          return parsed values here
        except: 

Вы также можете упростить это с помощью функций фильтра и карты:

lines = filter( lambda line: parseable(line), f.readlines())
values = map (parse, lines)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...