2013-07-09 2 views
1

У меня есть вкладка разделителями файл с \ п EOL символов, который выглядит примерно так:Удаление нескольких EOL в файле

User Name\tCode\tTrack\tColor\tNote\n\nUser Name2\tCode2\tTrack2\tColor2\tNote2\n 

Я принимаю этот входной файл и переформатирование его в список с помощью вложенного split('\t'). Список должен выглядеть следующим образом:

[['User Name','Code','Track','Color','Note'], 
['User Name2','Code2','Track2','Color2','Note2']] 

программное обеспечение, которое генерирует файл позволяет пользователю нажать клавишу «Ввод» любое количество раз при заполнении поля «Примечание». Он также позволяет пользователю нажимать «вводить», создавая любое количество строк новой строки без ввода какого-либо видимого текста в поле «Примечание».

Наконец, пользователь может нажать «ввести» любое количество раз в середине «примечания», создавая несколько абзацев, но это было бы таким редким явлением с операционной точки зрения, что я готов оставить эту возможность не если это усложняет код. Эта возможность действительно, очень низкий приоритет.

Как видно из вышеприведенного примера, эти действия могут приводить к последовательности кодов «\ n \ n ...» любой длины, предшествующей, завершающей или заменяющей поле «Примечание». Или поставить его таким образом, следующие замены требуются прежде, чем я могу поместить объект файла в списке:

\t\n\n... preceding "Note" must become \t 
\n\n... trailing "note" must become \n 
\n\n... in place of "note" must become \n 
\n\n... in the middle of the text note must become a single whitespace, if easy to do 

Я попытался с помощью полосы() и заменить() методы не увенчались успехом. Нужно ли копировать файл-файл во что-то другое прежде, чем метод replace() может быть использован на нем?

У меня есть опыт работы с Awk, но я надеюсь, что регулярные выражения для этого не нужны, поскольку я очень новичок в Python. Это код, который мне нужно улучшить, чтобы адресовать несколько строк новой строки:

marker = [i.strip() for i in open('SomeFile.txt', 'r')] 

marker_array = [] 
for i in marker: 
    marker_array.append(i.split('\t')) 

for i in marker_array: 
    print i 
+0

Вы можете изменить программное обеспечение, которое генерирует 'SomeFile.txt'? Если да, то написано ли оно на Python? – falsetru

+0

Может ли пользователь вводить вкладки в поле «Примечание»? – llb

+1

Это помогло бы, если бы вы использовали модуль 'csv' для * записи * этих данных и правильно указывали поле Note. –

ответ

4

Count язычки; если вы полагаете, что поле примечания никогда не имеет 4 вкладки на одной линии в нем, вы можете собрать записку, пока вы не найдете строку, которая делает есть 4 вкладки в нем:

def collapse_newlines(s): 
    # Collapse multiple consecutive newlines into one; removes trailing newlines 
    return '\n'.join(filter(None, s.split('\n'))) 

def read_tabbed_file(filename): 
    with open(filename) as f: 
     row = None 
     for line in f: 
      if line.count('\t') < 4: # Note continuation 
       row[-1] += line 
       continue 

      if row is not None: 
       row[-1] = collapse_newlines(row[-1]) 
       yield row 

      row = line.split('\t') 

     if row is not None: 
      row[-1] = collapse_newlines(row[-1]) 
      yield row 

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

Теперь используйте функцию read_tabbed_file() как генератор и петли над результатами:

for row in read_tabbed_file(yourfilename): 
    # row is a list of elements 

Демо:

>>> open('/tmp/test.csv', 'w').write('User Name\tCode\tTrack\tColor\tNote\n\nUser Name2\tCode2\tTrack2\tColor2\tNote2\n') 
>>> for row in read_tabbed_file('/tmp/test.csv'): 
...  print row 
... 
['User Name', 'Code', 'Track', 'Color', 'Note'] 
['User Name2', 'Code2', 'Track2', 'Color2', 'Note2'] 
+0

В этом случае я, вероятно, прочитал бы весь файл в виде строки и использовал splitlines(), чтобы избежать разворачивания дескриптора файла до тех пор, пока генератор не остановится. – llb

+1

@llb: А что, если файл на миллион строк короткий? Открытый дескриптор файла дешев. Удерживать все данные в памяти нет. –

1

Первой проблемой, с которой вы столкнулись, является in, который пытается быть полезным и читает в одной строке текста из файла за раз.

>>> [i for i in open('SomeFile.txt', 'r') ] 
['User Name\tCode\tTrack\tColor\tNote\n', '\n', 'User Name2\tCode2\tTrack2\tColor2\tNote2\n', '\n'] 

Добавление в вызове .strip() делает раздеть пробелы из каждой строки, но это оставляет вас с пустыми строками - он не принимает эти пустые элементы из списка.

>>> [i.strip() for i in open('SomeFile.txt', 'r') ] 
['User Name\tCode\tTrack\tColor\tNote', '', 'User Name2\tCode2\tTrack2\tColor2\tNote2', ''] 

Однако, вы можете предоставить в if пункте в списке понимание, чтобы сделать его падение линии, которые имеют только перевод строки:

>>> [i.strip() for i in open('SomeFile.txt', 'r') if len(i) >1 ] 
['User Name\tCode\tTrack\tColor\tNote', 'User Name2\tCode2\tTrack2\tColor2\tNote2'] 
>>> 
+0

Обратите внимание, что поля примечания OP могут содержать встроенные новые строки, а также начало или конец строк новой строки. Разделение на новые строки (или итерация по потоку) не будет эффективно обрабатывать этот случай. – llb

+0

Правильно, но обратите внимание, что OP также сказал, что они не заботятся о том, чтобы справиться с этой морщиной прямо сейчас (или, по крайней мере, это низкий приоритет). –

+0

Спасибо за этот очень простой ответ. Это почти работает, но я решил пойти с генераторным решением выше. –

Смежные вопросы