2010-04-27 5 views
0

сгенерированный сообщение периодический компьютер (упрощенный):многострочный шаблону в Python

Hello user123, 

- (604)7080900 
- 152 
- minutes 

Regards 

Использование Python, как можно извлечь "(604) 7080900", "152", "минут" (т.е. любой текст после ведущего шаблона "- ") между двумя пустыми строками (пустая строка - \n\n после «Hello user123» и \n\n до «С уважением»). Еще лучше, если список строк результатов хранится в массиве. Благодаря!

изменить: количество строк между двумя пустыми строками не фиксировано.

2nd редакция:

например.

hello 

- x1 
- x2 
- x3 

- x4 

- x6 
morning 
- x7 

world 

x1 x2 x3 хороши, так как все линии окружены 2 пустых строк, x4 также хорошо по той же причине. x6 не является хорошим, потому что после него нет пустой строки, x7 не хорош, поскольку перед ним нет пробела. x2 хорош (не как x6, x7), потому что линия впереди - хорошая линия, и строка, следующая за ней, также хороша.

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

a continuous of good lines between 2 empty lines 

good line must have leading "- " 
good line must follow an empty line or follow another good line 
good line must be followed by an empty line or followed by another good line 

благодаря

ответ

3

Самый простой подход заключается в переходе этих линий (предполагая, что у вас есть список строк, или файл или разделите строку на список строк), пока не увидите строку, которая только '\n', а затем проверьте, что каждая строка начинается с '- ' (с использованием метода строки startswith) и отрезая ее, сохраняя результат, пока не найдете другая пустая строка. Например:

# if you have a single string, split it into lines. 
L = s.splitlines() 
# if you (now) have a list of lines, grab an iterator so we can continue 
# iteration where it left off. 
it = iter(L) 
# Alternatively, if you have a file, just use that directly. 
it = open(....) 

# Find the first empty line: 
for line in it: 
    # Treat lines of just whitespace as empty lines too. If you don't want 
    # that, do 'if line == ""'. 
    if not line.strip(): 
     break 
# Now starts data. 
for line in it: 
    if not line.rstrip(): 
     # End of data. 
     break 
    if line.startswith('- '): 
     data.append(line[:2].rstrip()) 
    else: 
     # misformed data? 
     raise ValueError, "misformed line %r" % (line,) 

Отредактировано: Поскольку вы уточнить, что вы хотите делать, вот обновленная версия петель. Он больше не зацикливается дважды, но вместо этого собирает данные, пока не встретит «плохую» строку, и либо сохраняет, либо удаляет собранные строки, когда сталкивается с разделителем блоков. Он не нуждается в явном итератора, так как он не перезапускать итерации, так что вы можете просто передать ему список (или любой итерацию) линий:

def getblocks(L): 
    # The list of good blocks (as lists of lines.) You can also make this 
    # a flat list if you prefer. 
    data = [] 
    # The list of good lines encountered in the current block 
    # (but the block may still become bad.) 
    block = [] 
    # Whether the current block is bad. 
    bad = 1 
    for line in L: 
     # Not in a 'good' block, and encountering the block separator. 
     if bad and not line.rstrip(): 
      bad = 0 
      block = [] 
      continue 
     # In a 'good' block and encountering the block separator. 
     if not bad and not line.rstrip(): 
      # Save 'good' data. Or, if you want a flat list of lines, 
      # use 'extend' instead of 'append' (also below.) 
      data.append(block) 
      block = [] 
      continue 
     if not bad and line.startswith('- '): 
      # A good line in a 'good' (not 'bad' yet) block; save the line, 
      # minus 
      # '- ' prefix and trailing whitespace. 
      block.append(line[2:].rstrip()) 
      continue 
     else: 
      # A 'bad' line, invalidating the current block. 
      bad = 1 
    # Don't forget to handle the last block, if it's good 
    # (and if you want to handle the last block.) 
    if not bad and block: 
     data.append(block) 
    return data 

И вот оно в действии:

>>> L = """hello 
... 
... - x1 
... - x2 
... - x3 
... 
... - x4 
... 
... - x6 
... morning 
... - x7 
... 
... world""".splitlines() 
>>> print getblocks(L) 
[['x1', 'x2', 'x3'], ['x4']] 
+0

@Thomas Wouters, «для строки» не является надежным (в противном случае я не стану отмечать этот вопрос многострочным ;-) Я могу начать только сопоставление _after_ «\ n \ n-» (два строчных файла, затем главный знак минус и пространство) – ohho

+0

Это не было (и все еще не так) в вашем вопросе, но основной подход остается тем же. Вы все равно можете использовать итерацию поверх строк, но вам нужно будет уточнить, что у вас есть на самом деле, и действительно хотите, если вы хотите, чтобы я записал пример. Что делать, если есть линии, которые не начинаются с «-» между строками? Что делать, если есть несколько таких блоков? Что делать, если строки не пусты, а просто имеют пробелы? –

+0

см. Мое второе редактирование. – ohho

4
>>> import re 
>>> 
>>> x="""Hello user123, 
... 
... - (604)7080900 
... - 152 
... - minutes 
... 
... Regards 
... """ 
>>> 
>>> re.findall("\n+\n-\s*(.*)\n-\s*(.*)\n-\s*(minutes)\s*\n\n+",x) 
[('(604)7080900', '152', 'minutes')] 
>>> 
+0

@ S.Mark, извините, что я не сделал вопрос ясным, см. Редактирование о неопределенном количестве строк между двумя пустыми строками. – ohho

+0

@Horace, добавлено \ n +, чтобы соответствовать более чем двум пустым строкам – YOU

+0

@ S.Mark, можно ли забрать (минуты) из re? так как «минут» не обязательно появляется в последней строке – ohho

1
>>> s = """Hello user123, 

- (604)7080900 
- 152 
- minutes 

Regards 
""" 
>>> import re 
>>> re.findall(r'^- (.*)', s, re.M) 
['(604)7080900', '152', 'minutes'] 
1
l = """Hello user123, 

- (604)7080900 
- 152 
- minutes 

Regards 

Hello user124, 

- (604)8576576 
- 345 
- minutes 
- seconds 
- bla 

Regards""" 

сделать это:

result = [] 
for data in s.split('Regards'): 
    result.append([v.strip() for v in data.split('-')[1:]]) 
del result[-1] # remove empty list at end 

и имеют следующее:

>>> result 
[['(604)7080900', '152', 'minutes'], 
['(604)8576576', '345', 'minutes', 'seconds', 'bla']] 
Смежные вопросы