2010-10-06 8 views
3

У меня есть некоторые данные (текстовые файлы), которые отформатированы самым неравномерным образом, о котором можно было подумать. Я пытаюсь свести к минимуму объем ручной работы по разбору этих данных.Как удалить переменные пространства в каждой строке текстового файла на основе специального условия - однострочный в Python?

Образец данных:

Name  Degree  CLASS  CODE  EDU  Scores 
-------------------------------------------------------------------------------------- 
John Marshall  CSC 78659944 89989  BE 900 
Think Code DB I10 MSC 87782 1231 MS   878 
Mary 200 Jones CIVIL  98993483 32985  BE  898 
John G. S Mech 7653 54 MS 65 
Silent Ghost Python Ninja 788505 88448 MS Comp 887 

Условия:?

  • Более одного помещения должны быть сжаты до ограничителя (трубы лучше конечной целью является сохранение этих файлов в базе данных).
  • За исключением первого столбца, в других столбцах не будет пробелов, поэтому все эти пространства могут быть сжаты в трубу.
  • Только первая колонка может содержать несколько слов с пробелами (Mary K Jones). Остальные столбцы - это в основном числа и некоторые алфавиты.
  • Первый и второй столбцы - это строки. У них почти всегда есть более одного пространства между ними, так что мы можем различать два столбца. (Если есть одно место, это риск, который я готов принять, учитывая ужасное форматирование!).
  • Число столбцов меняется, поэтому нам не нужно беспокоиться о именах столбцов. Все, что мы хотим - извлечь данные каждого столбца.

Надеюсь, я имел смысл! У меня такое чувство, что эта задача может быть выполнена в oneliner. Я не хочу, чтобы петля, петля, петля :(

Muchos GRACIAS «питонисты» для чтения на всем пути и не дойдя до этого предложения

+0

Данные, которые вы показываете, выглядят так, как будто у них были вкладки, а не пробелы в нем, чтобы данные в каждом столбце совпадали с заголовком - обратите внимание, что заголовки располагаются соответствующим образом. Вы совершенно уверены, что он будет искажен до того, как вы его получите? Вы уверены, что в данных нет вкладок? Обратите внимание, что регулярное выражение в принятом в настоящее время ответе использует '\ s', который будет соответствовать любому символу пробела (т. Е. Соответствует вкладке, а также пробелу) - регулярное выражение все еще« работает », если вы замените« \ s »на« »? –

+0

Интервал настолько непоследовательный, следовательно, этот маршрут. Я заменяю все вкладки (\ t на 3 пробела). Я все еще проверяю версию регулярного выражения от SilentGhost. Я мог бы пойти с предыдущим вариантом, он просто работает. Небольшая комната для ошибок, но это то, к чему я готов, учитывая сумасшедшее форматирование этих документов. Спасибо! – ThinkCode

+0

Итак, вы разбили ваши данные, изменив каждую вкладку на 3 пробела, и вы не сказали нам ??? Это примерно -100, откуда я родом, но я перестану дышать и продолжаю ... –

ответ

3

Он по-прежнему кажется фолиант, что есть какой-то формат в файлах:

>>> regex = r'^(.+)\b\s{2,}\b(.+)\s+(\d+)\s+(\d+)\s+(.+)\s+(\d+)' 
>>> for line in s.splitlines(): 
    lst = [i.strip() for j in re.findall(regex, line) for i in j if j] 
    print(lst) 


[] 
[] 
['John Marshall', 'CSC', '78659944', '89989', 'BE', '900'] 
['Think Code DB I10', 'MSC', '87782', '1231', 'MS', '878'] 
['Mary 200 Jones', 'CIVIL', '98993483', '32985', 'BE', '898'] 
['John G. S', 'Mech', '7653', '54', 'MS', '65'] 
['Silent Ghost', 'Python Ninja', '788505', '88448', 'MS Comp', '887'] 

Regex довольно прост, единственное, что вам нужно обратить внимание на те разделители (\s) и изломы слова (\b) в случае первого разделителя. Обратите внимание, что, когда линия не будет соответствовать вы получите пустой список как lst. Это будет флаг чтения, чтобы вызвать взаимодействие пользователя, описанное ниже. Также вы можете пропустить строки заголовка, выполнив:

>>> file = open(fname) 
>>> [next(file) for _ in range(2)] 
>>> for line in file: 
    ... # here empty lst indicates issues with regex 

Предыдущие варианты:

>>> import re 
>>> for line in open(fname): 
    lst = re.split(r'\s{2,}', line) 
    l = len(lst) 
    if l in (2,3): 
     lst[l-1:] = lst[l-1].split() 
    print(lst) 

['Name', 'Degree', 'CLASS', 'CODE', 'EDU', 'Scores'] 
['--------------------------------------------------------------------------------------'] 
['John Marshall', 'CSC', '78659944', '89989', 'BE', '900'] 
['Think Code DB I10', 'MSC', '87782', '1231', 'MS', '878'] 
['Mary 200 Jones', 'CIVIL', '98993483', '32985', 'BE', '898'] 
['John G. S', 'Mech', '7653', '54', 'MS', '65'] 

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

if l < 3: 
    lst = line.split() 
    print(lst) 
    iname = input('enter indexes that for elements of name: ')  # use raw_input in py2k 
    idegr = input('enter indexes that for elements of degree: ') 

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

+0

Ничего себе, потрясающе! он работает по большей части, но в тех случаях, когда степень отделена одним пространством, он не работает. [John G. S Mech 7653 54 MS 65]. Наслаждайтесь супер быстрым решением! – ThinkCode

+0

@ThinkCode: * степень отделена одним пробелом * отделенным от чего? имя? – SilentGhost

+1

@ Подумайте: если у вас есть фиксированный список степеней, вы можете проверить 'lst [1]' против него и попробовать ручное разделение на эти записи. – SilentGhost

2

Вариант ответа SilentGhost, на этот раз сначала разделив имя от остальных (разделенных двумя или более пробелами), а затем просто разделив остальные и, наконец, сделав один список.

import re 

for line in open(fname): 
    name, rest = re.split('\s{2,}', line, maxsplit=1) 
    print [name] + rest.split() 
1

Этот ответ был написан после того, как OP признался меняется каждую вкладку («\ т») в своих данных 3 пространств (и не упоминать его в вопросе).

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

Вместо того, чтобы делать line.replace('\t', ' ' * 3) попробуйте line.expandtabs().

Docs for expandtabs are here.

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

Вы уверены, что вторая строка - «-» или есть промежутки между столбцами? Причины спрашивать, что я когда-то нужно разобрать множество различных файлов из механизма отчетов запросов к базе данных, который представил результаты, как это:

RecordType ID1     ID2   Description   
----------- -------------------- ----------- ---------------------- 
1   12345678    123456  Widget     
4   87654321    654321  Gizmoid 

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

sizes = map(len, dash_line.split()) 

Если expandtabs() не работает, редактировать свой вопрос, чтобы показать, что именно вы имеете то показать результат print repr(line) в течение первых 5 или около линий (в том числе в строке заголовка). Возможно, было бы полезно, если бы вы могли сказать, какое программное обеспечение создает эти файлы.

+0

Проблема в том, что текстовые файлы, которые я получил обрабатывать, имеют несколько разных форматов, без столбцов фиксированной ширины - в некоторых записях разные вкладки и пробелы (смешанные). Это повсюду. Некоторые даже не имеют промежутков. Вторая строка иногда имела разделители для обозначения начала столбца. К этим можно легко позаботиться. Когда нет разделителя, они могут или не иметь тире. Они исчезнут в процессе чистки. Различные источники получают одинаковые данные, отформатированные другим способом. – ThinkCode

+0

@ThinkCode: «В некоторых записях есть различные вкладки и пробелы (смешанные)» - да, это описание соответствует диалогу «необходимость для расширения». «Они исчезнут в процессе чистки» - у вас есть интересная интерпретация «чистки». Я сочувствую вашей общей проблеме, но выбирая вкладки на 3 пространства и не говоря об этом, это совсем не очень хорошая идея. –

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

  • Нет связанных вопросов^_^