2013-05-03 4 views
1

У меня есть следующий вход:Regex для многострочной строки?

str = """ 

    Q: What is a good way of achieving this? 

    A: I am not sure. Try the following: 

    1. Take this first step. Execute everything. 

    2. Then, do the second step 

    3. And finally, do the last one 



    Q: What is another way of achieving this? 

    A: I am not sure. Try the following alternatives: 

    1. Take this first step from before. Execute everything. 

    2. Then, don't do the second step 

    3. Do the last one and then execute the above step 

""" 

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

(?ms)^[\s#\-\*]*(?:Q)\s*:\s*(\S.*?\?)[\s#\-\*]+(?:A)\s*:\s*(\S.*)$ 

Но, я в состоянии захватить вход следующим образом:

('Q', 'What is a good way of achieving this?') 
('A', "I am not sure. Try the following:\n 1. Take this first step. Execute everything.\n 2. Then, do the second step\n 3. And finally, do the last one\n\n Q: What is another way of achieving this?\n A: I am not sure. Try the following alternatives:\n 1. Take this first step from before. Execute everything.\n 2. Then, don't do the second step\n 3. Do the last one and then execute the above step\n") 

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

+1

Есть ли причина, по которой вы не просто читаете ее по строкам? –

+1

@WesAlvaro: Итак, вы предлагаете, чтобы я читал строки за строкой, а затем обрабатывал это с использованием подхода на основе состояний, а не регулярного выражения? – Legend

+1

Является ли это глупым подходом к разбиению на 'Q:' сначала (вы получаете два элемента), а затем разбивается на 'A:' (вы получаете четыре: '[[Q, A], [Q, A]]')? –

ответ

1

Ленточный, но не самый лучший способ решить его - взорвать строку «Q:», а затем просто проанализировать детали с помощью простых /Q:(.+)A:(.+)/msU (в общем регулярном выражении).

1

Просто использование этого отлично подходит для меня. Требуется только обрезка пробела.

(?s)(Q):((?:(?!A:).)*)(A):((?:(?!Q:).)*) 

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

>>> import re 
>>> str = """ 
... 
...  Q: What is a good way of achieving this? 
... 
...  A: I am not sure. Try the following: 
... 
...  1. Take this first step. Execute everything. 
... 
...  2. Then, do the second step 
... 
...  3. And finally, do the last one ...  ... ... 
...  Q: What is another way of achieving this? 
... 
...  A: I am not sure. Try the following alternatives: 
... 
...  1. Take this first step from before. Execute everything. 
... 
...  2. Then, don't do the second step 
... 
...  3. Do the last one and then execute the above step 
... 
... """ 
>>> regex = r"(?s)(Q):((?:(?!A:).)*)(A):((?:(?!Q:).)*)" 
>>> match = re.findall(regex, str) 
>>> map(lambda x: [part.strip().replace('\n', '') for part in x], match) 
[['Q', 'What is a good way of achieving this?', 'A', 'I am not sure. Try the following: 1. Take this first step. Execute everything. 2. Then, do the second step 3. And finally, do the last one'], ['Q', 'What is another way of achieving this?', 'A', "I am not sure. Try the following alternatives: 1. Take this first step from before. Execute everything. 2. Then, don't do the second step 3. Do the last one and then execute the above step"]] 

Даже добавил немного штучка, чтобы помочь вам очистить пробельные в конце там.

0

Я не настолько умен, чтобы написать огромное регулярное выражение (пока), так вот мое, не регулярное выражение решения -

>>> str = """ 

    Q: What is a good way of achieving this? 

    A: I am not sure. Try the following: 

    1. Take this first step. Execute everything. 

    2. Then, do the second step 

    3. And finally, do the last one 



    Q: What is another way of achieving this? 

    A: I am not sure. Try the following alternatives: 

    1. Take this first step from before. Execute everything. 

    2. Then, don't do the second step 

    3. Do the last one and then execute the above step 

""" 
>>> qas = str.strip().split('Q:') 
>>> clean_qas = map(lambda x: x.strip().split('A:'), filter(None, qas)) 
>>> print clean_qas 
[['What is a good way of achieving this?\n\n ', ' I am not sure. Try the following:\n\n 1. Take this first step. Execute everything.\n\n 2. Then, d 
o the second step\n\n 3. And finally, do the last one'], ['What is another way of achieving this?\n\n ', " I am not sure. Try the following alternativ 
es:\n\n 1. Take this first step from before. Execute everything.\n\n 2. Then, don't do the second step\n\n 3. Do the last one and then execute the 
above step"]] 

Вы должны очистить пробельные хотя. Или вы могли бы сделать то, что сказал Пучик.

Просто для удовольствия -

>>> clean_qas = map(lambda x: map(lambda s: s.strip(), x.strip().split('A:')), filter(None, qas)) 
>>> print clean_qas 
[['What is a good way of achieving this?', 'I am not sure. Try the following:\n\n 1. Take this first step. Execute everything.\n\n 2. Then, do the sec 
ond step\n\n 3. And finally, do the last one'], ['What is another way of achieving this?', "I am not sure. Try the following alternatives:\n\n 1. Take 
this first step from before. Execute everything.\n\n 2. Then, don't do the second step\n\n 3. Do the last one and then execute the above step"]] 

выглядит некрасиво, хотя.

0

Слегка модифицируя оригинальное решение:

(?ms)^[\s#\-\*]*(?:Q)\s*:\s+(\S[^\n\r]*\?)[\s#\-\*]+(?:A)\s*:\s+(\S.*?)\s*(?=$|Q\s*:\s+) 
  • Вопросы и ответы должны иметь по крайней мере один пробел после :.
  • Вместо того, чтобы отвечать на вопросы без жадности (что не допускает наличия нескольких ? в одном вопросе), не допускайте появления новых строк в вопросах.
  • Вместо того, чтобы соответствовать концу строки, не с жадностью совпадать до либо, за которым следует конец строки или, а затем другой вопрос.

Используйте re.findall, чтобы получить все вопросы/ответы.

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