Синтаксический анализ текстового файла и вывод в новый файл

#python #parsing

#python #синтаксический анализ

Вопрос:

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

Вот краткий пример.

 ; Record 1
@FULLTEXT PAGE
@T R000358
@C ENDDOC# R000358
@C BEGATTACH R000358
@C ENDATTACH R000358
@C MAILSTORE No
@C AUTHOR 
@C BCC 
@C CC 
@C COMMENTS 
@C ATTACH 
@C DATECREATED 11/23/2010
@C DATELASTMOD 07/18/2010
@C DATELASTPRNT 
@C DATERCVD 
@C DATESENT 
@C FILENAME wrangling.wpd
@C LASTAUTHOR 
@C ORGANIZATION 
@C REVISION 
@C SUBJECT 
@C TIMEACCESSED 00:00:00
@C TIMECREATED 15:21:34
@C TIMELASTMOD 09:04:12
@C TIMELASTPRNT 
@C TIMERCVD 
@C TIMESENT 
@C TITLE 
@C TO 
@C FROM 
 

Для каждой «записи» «@C» и «@T» — это разделитель полей, за которым следует пробел, затем имя поля, за которым следует пробел, затем данные поля. Мне нужно, чтобы все данные поля были разделены одной строкой, а не столбцом, как показано выше.

Я хочу вывести в новый файл каждую запись примерно так.

«R000358», «R000358», «R000358», «R000358», «Нет» и т. Д. И т. Д. (в одной строке)

Этот пример разделен запятыми, но он может измениться, но я решил, что начну с этого.

Любая помощь будет оценена. Заранее спасибо.

Комментарии:

1. Что такое разделитель записей?

Ответ №1:

Неясно, как разделяются записи и что именно вы хотели бы сделать со своим выводом, но вот простой анализатор, который должен помочь вам начать:

 s = '''
; Record 1
@FULLTEXT PAGE
@T R000358
@C ENDDOC# R000358
@C BEGATTACH R000358
@C ENDATTACH R000358
@C MAILSTORE No
@C AUTHOR 
@C BCC 
@C CC 
@C COMMENTS 
@C ATTACH 
@C DATECREATED 11/23/2010
@C DATELASTMOD 07/18/2010
@C DATELASTPRNT 
@C DATERCVD 
@C DATESENT 
@C FILENAME wrangling.wpd
@C LASTAUTHOR 
@C ORGANIZATION 
@C REVISION 
@C SUBJECT 
@C TIMEACCESSED 00:00:00
@C TIMECREATED 15:21:34
@C TIMELASTMOD 09:04:12
@C TIMELASTPRNT 
@C TIMERCVD 
@C TIMESENT 
@C TITLE 
@C TO 
@C FROM
'''.splitlines()

records = []
record = {}
for line in s:
    if line.startswith('; Record'):
        record = {}
        records.append(record)
    elif line.startswith(('@T ', '@C ')):
        f = line.split()
        fieldname = f[1]
        i = line.find(fieldname)   len(fieldname)
        fieldvalue = line[i:].lstrip()
        record[fieldname] = fieldvalue

import pprint
pprint.pprint(records)
 

Удачи с Python.

Ответ №2:

 def getRecordRows( file, start_characters, delimiter):
    returnRows = []
    for line in open(file):
        if line.startswith(start_characters):
             returnRows.append( line[len(start_characters):] )
    return delimiter.join( returnRows )
 

Пример использования:

 file = /path/to/file
getRecordRows(file, '@T', ',')
 

Ответ №3:

Начните с открытия файла:

 with open('inputfile','r') as fil:
    # file read-in stuff here
 

Используйте with идиому, если вы используете python 2.5 и выше, в противном случае выполните:

 try:
    fil = open('inputfile','r')
    # file read-in stuff here
finally:
    fil.close()
 

Чтобы преобразовать содержимое файла в строки, проверьте file.readline() (читает по одной строке за раз; использовать для больших файлов) и file.readlines() (считывает весь файл в список, по одной строке на запись) здесь .

Чтобы записать файл, используйте приведенную выше логику для чтения, за исключением открытия файла в режиме записи, например: open('outputfile','w')

Чтобы обработать форматирование для вашего выходного файла, посмотрите на строковые методы здесь. В частности, взгляните на str.split() и str.join() , которые позволяют легко разбивать строки на списки и объединять элементы списка в строки с помощью разделителя.

Ответ №4:

 record = None
records = []

with open('records.dat') as stream:
    for line in stream:
        item = line.strip().split()
        if not item:
            continue
        if item[0] == ';':
            record = []
            records.append((item[-1], record))
        elif record is not None:
            if item[0] == '@C' and len(item) <= 2:
                record.append('')
            elif item[0] in ('@T', '@C'):
                record.append(item[-1])

for identifier, record in records:
    print '[%s]: %s' % (identifier, ', '.join(record))