Вопрос:

повторение в регулярном выражении в python

python regex python-2.7

1270 просмотра

3 ответа

565 Репутация автора

У меня есть файл со строками, например:

aaa$bb$ccc$ddd$eee
fff$ggg$hh$iii$jj

Мне нужно взять то, что находится внутри $$, поэтому ожидаемый результат:

 $bb$
 $ddd$
 $ggg$
 $iii$

Мой результат:

$bb$
$ggg$

Мое решение:

m = re.search(r'$(.*?)$', line)
    if m is not None:
        print m.group(0)

Есть идеи, как улучшить мои регулярные выражения? Я пробовал со знаком * и +, но я не уверен, как наконец его создать. Я искал похожий пост, но не смог его найти :(

Автор: degath Источник Размещён: 22.08.2016 08:50

Ответы (3)


6 плюса

367590 Репутация автора

Решение

Вы можете использовать re.findallс r'\$[^$]+\$'регулярным выражением:

import re
line = """aaa$bb$ccc$ddd$eee
fff$ggg$hh$iii$jj"""
m = re.findall(r'\$[^$]+\$', line)
print(m)
# => ['$bb$', '$ddd$', '$ggg$', '$iii$']

Посмотреть демо Python

Обратите внимание, что вам нужно экранировать $s и удалить группу захвата, re.findallчтобы вернуть $...$подстроки, а не только то, что находится внутри $s.

Детали шаблона :

  • \$ - символ доллара (буквальный)
  • [^$]+ - 1 или более символов, кроме $
  • \$ - буквальный символ доллара.

ПРИМЕЧАНИЕ . Класс символов[^$] с отрицанием, который соответствует любому символу , кроме указанного (-ых) в классе. Использование отрицательного класса символов здесь ускоряет сопоставление, поскольку .*?шаблон ленивых точек расширяется в каждой позиции в строке между двумя $s, таким образом предпринимая еще много шагов для завершения и возврата совпадения.

И вариант шаблона, чтобы получить только тексты внутри $...$s:

re.findall(r'\$([^$]+)\$', line) 
               ^     ^

Смотрите еще одну демонстрацию Python . Обратите внимание на (...)добавленную группу захвата, которая re.findallможет возвращать только то, что захвачено , а не то, что сопоставлено .

Автор: Wiktor Stribiżew Размещён: 22.08.2016 08:52

3 плюса

96093 Репутация автора

re.searchнаходит только первый матч. Возможно, вы захотите re.findall, который возвращает список строк или re.finditerвозвращает итератор объектов сопоставления. Кроме того, вы должны бежать $к \$, как и неэкранированные $средства «конец строки».


Пример:

>>> re.findall(r'\$.*?\$', 'aaa$bb$ccc$ddd$eee')
['$bb$', '$ddd$']
>>> re.findall(r'\$(.*?)\$', 'aaa$bb$ccc$ddd$eee')
['bb', 'ddd']

Еще одно улучшение будет использовать [^$]*вместо .*?; первое означает «ноль или более любых символов помимо $этого; это может потенциально избежать более патологического поведения при возврате».

Автор: Antti Haapala Размещён: 22.08.2016 08:53

1 плюс

47223 Репутация автора

Ваше регулярное выражение в порядке. re.searchнаходит только первое совпадение в строке. Вы ищете re.findall, который находит все непересекающиеся совпадения. Этот последний бит важен для вас, поскольку у вас есть одинаковый начальный и конечный разделители.

for m in m = re.findall(r'$(.*?)$', line):
    if m is not None:
        print m.group(0)
Автор: Mad Physicist Размещён: 22.08.2016 08:54
Вопросы из категории :
32x32