Утверждение Lookahead с несколькими значениями

79
2

У меня есть следующий текст:

[red]

aaa [bbb] hello

[blue]

aaa

[green]

ccc

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

keys = ('red', 'blue', 'green')
for key in keys:
match = re.search(r'\[' + key + r'\](.*)(?=(?:' + '|'.join(keys) + r'|$))',
text, flags=re.DOTALL)

print(key, match.group(1))

Я что-то пропускаю, потому что он ничего не соответствует. Есть идеи?

спросил(а) 2017-04-07T12:55:00+03:00 2 года, 8 месяцев назад
4
Решение
79

В конце концов, я решил не использовать регулярное выражение для соответствия содержимому раздела:

# Walk through the file line by line and collect text from the specific sections
keys = ('red', 'blue', 'green')
last_section = ''
for line in text.splitlines():
if line.startswith('#'):
continue

match = re.match(r'^\[(' + '|'.join(keys) + ')\]', line)
if match:
last_section = match.group(1)
continue

if last_section:
new_contents[last_section] += '\n' + line

for section in new_contents:
new_contents[section] = new_contents[section].strip()

ответил(а) 2017-04-07T14:58:00+03:00 2 года, 8 месяцев назад
Еще 3 ответа
33

Метод обработки строк, независимо от порядка вашего ключа в тексте. Если вы не хотите использовать регулярное выражение, надейтесь, что это поможет!

text = '[red]\naaa [bbb] hello\n[blue]\naaa\n[green]\nccc'

# keys = ('red', 'blue', 'green')
# keys = ('blue', 'red', 'green')
# keys = ('green', 'red', 'blue')
keys = ('green', 'blue', 'red')
# store key and index of key tuple
index_key_tuples = []

for key in keys:
index = text.find('[' + key + ']')
if index != -1:
index_key_tuples.append((index, key))
# sort the index key tuple
index_key_tuples.sort()

i = 0
size = len(index_key_tuples)
while i < size - 1:
# start index of content of key
item = index_key_tuples[i]
key = item[1]
start_index = item[0] + len(key) + 2 # 2 is for square bracket
# end index of content of key
next_item = index_key_tuples[i + 1]
end_index = next_item[0]
# content of key
key_content = text[start_index:end_index].strip()
print(key, key_content)
i += 1

# handle the last key
last_item = index_key_tuples[size-1]
key = last_item[1]
start_index = last_item[0] + len(key) + 2
key_content = text[start_index:].strip()
print(key, key_content)

ответил(а) 2017-04-07T15:13:00+03:00 2 года, 8 месяцев назад
31

Возможно, что-то вроде такого подхода может работать:

keys = ('red', 'blue', 'green')

res = re.findall(r'\[\w+\].?|([\w\[\] ]+)', text)
res = [x for x in res if x]

for n in range(len(keys)):
print(keys[n], res[n])

Результат:


('red', 'aaa [bbb] hello')
('blue', 'aaa')
('green', 'ccc')

Пример:

https://regex101.com/r/p55ckh/1

ответил(а) 2017-04-07T13:54:00+03:00 2 года, 8 месяцев назад
33

Вы можете найти регулярное выражение! Вы можете сгруппировать свой раздел и значения в нем вместе,

>>> import re
>>> print re.findall(r'\[(\w*)\]([\w \n]*)',text)
[('red', '\n\naaa '), ('bbb', ' hello\n\n'), ('blue', '\n\naaa\n\n'), ('green', '')]

здесь для вашего раздела \[(\w*)\] и ([\w \n]*) для содержимого вашего раздела. С этим результатом в руке вы можете разделить или заменить избыточные символы перевода строки!

Надеюсь, поможет!

ответил(а) 2017-04-07T13:26:00+03:00 2 года, 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема