Почему регулярное выражение возвращает несколько совпадений? [Дубликат]

Представьте, что у вас есть продукт под названием «Zebra», который может быть дополнен плагинами. Он находит плагины, ища библиотеки DLL в некоторых каталогах. Он загружает все эти DLL и использует отражение для поиска любых классов, которые реализуют IZebraPlugin, а затем вызывает методы этого интерфейса для связи с плагинами.

Это делает его полностью независимым от какого-либо конкретного класса плагина - ему все равно, что представляют собой классы. Он заботится только о том, чтобы они соответствовали спецификации интерфейса.

Интерфейсы - это способ определения точек расширяемости, подобных этому. Код, который говорит с интерфейсом, более слабо связан - на самом деле он не связан вообще с каким-либо другим конкретным кодом. Он может взаимодействовать с плагинами, написанными годами позже людьми, которые никогда не встречались с оригинальным разработчиком.

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

10
задан Alan Moore 10 August 2015 в 16:01
поделиться

2 ответа

s = r'abc123d, hello 3.1415926, this is my book'
print re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s)

Вам не нужно escape дважды, когда вы используете raw mode.

Выход: ['123', '3.1415926']

Также тип возврата будет списком strings .Если вы хотите, чтобы возвращаемый тип, как integers и floats, использовал map

import re,ast
s = r'abc123d, hello 3.1415926, this is my book'
print map(ast.literal_eval,re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s))

Выход: [123, 3.1415926]

5
ответ дан vks 20 August 2018 в 23:15
поделиться
  • 1
    Хотя это регулярное выражение менее эффективно, чем мое, я признаю, что трюк с ast является крутым (хотя в OP не требуется). – Wiktor Stribiżew 10 August 2015 в 08:51
  • 2
    @stribizhev я прочитал один из его комментариев .... @stribizhev, it's not, '3.1415926' should be a float number in the result, поэтому я включил это в свой ответ :) – vks 10 August 2015 в 08:53
  • 3
    вы двое оба гения, мне трудно выбрать, какой из них принять. :) – O'Skywalker 10 August 2015 в 08:53
  • 4
    @ O'Skywalker: выберите тот, который работает для вас лучше всего. Просто, пожалуйста, не передумайте завтра, никто из нас не будет рад увидеть -15 очков падения репутации :) – Wiktor Stribiżew 10 August 2015 в 08:55
  • 5
    @ O'Skywalker ничего подобного гения: P .......... просто практика ....... вы скоро станете aficianado !!!!!!!! – vks 10 August 2015 в 08:56

Здесь есть две вещи:

  • re.findall возвращает захваченные тексты, если шаблон регулярного выражения содержит в нем группы захвата
  • часть r'\\.' в вашем шаблон соответствует двум последовательным символам, \ и любому символу, отличному от новой строки.

См. ссылку findall :

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

Обратите внимание, что чтобы re.findall возвращали только совпадающие значения, вы обычно можете

  • удаляет избыточные группы захвата (например, (a(b)c) -> abc)
  • преобразует все группы захвата в , не захватывая (то есть замените ( на (?:) , если отсутствуют обратные ссылки, которые относятся к значениям группы в шаблоне (см. ниже)
  • вместо re.finditer использовать [x.group() for x in re.finditer(pattern, s)])

В вашем случае findall вернул все захваченные тексты, которые были пустыми, потому что вы \\ в [литерале] строки r'', которые пытались сопоставить литерал \.

Чтобы соответствовать номерам, вам нужно использовать

-?\d*\.?\d+

Регулярное выражение соответствует:

  • -? - Дополнительный знак минус
  • \d* - Необязательные цифры
  • \.? - Дополнительный десятичный разделитель
  • \d+ - 1 или более цифр.

См. demo

Вот демон IDEONE :

import re
s = r'abc123d, hello 3.1415926, this is my book'
pattern = r'-?\d*\.?\d+'
L = re.findall(pattern, s)
print(L)
8
ответ дан Wiktor Stribiżew 20 August 2018 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: