сделать регулярное выражение более конкретным, чтобы исключить определенные символы - PullRequest
0 голосов
/ 04 октября 2019
import re
s = '01.11.11 12/12/1981 1*51*12 . 22|1|13 03-02-1919 1-22-12 or 01-23-18 or 03-23-1984 01.11.18 or 2.2.17 or 02.02.18 or 12.1.16 12.23.1943 01-23-11 not 12.23.192 not 02.02.1'

У меня есть следующая строка s, и я хочу извлечь все даты, разделенные на 3 элемента: 1) период, например, 01.11.11 или 2) тире, например, 1-22-12 или 3). обратная косая черта, например 12/12/1981.

Для этого я попробовал следующее

reg = r'\d{1,2}.\d{1,2}.(?:\d{4}|\d{2})' 
r1 = re.findall(reg,s)

Это работает, но дает некоторые нежелательные вещи, такие как '1*51*12' и 22|1|13'

['01.11.11',
 '12/12/1981',
 '1*51*12',
 '22|1|13',
 '03-02-1919',
 '1-22-12',
 '01-23-18',
 '03-23-1984',
 '01.11.18',
 '2.2.17',
 '02.02.18',
 '12.1.16',
 '12.23.1943',
 '01-23-11',
 '12.23.19']

Я хочу, чтобы мой вывод был

['01.11.11',
 '12/12/1981',
 '03-02-1919',
 '1-22-12',
 '01-23-18',
 '03-23-1984',
 '01.11.18',
 '2.2.17',
 '02.02.18',
 '12.1.16',
 '12.23.1943',
 '01-23-11',
 '12.23.19']

Как мне настроить reg, чтобы он был более конкретным и получить желаемый результат?

Ответы [ 3 ]

2 голосов
/ 04 октября 2019

Если вы хотите сопоставить один и тот же разделитель для всего шаблона типа даты, вы можете использовать группу захвата и обратную ссылку \1, чтобы такая дата, как 12/12.1981, не совпадала.

Обратите внимание, что шаблон не проверяет саму дату.

\b\d{1,2}([./-])\d{1,2}\1(?:\d{4}|\d{2})\b
  • \b Граница слова
  • \d{1,2} Соответствие 1-2 цифрам
  • ([./-]) Группа захвата 1, совпадение . / или -
  • \d{1,2}\1 Совпадение 1-2 цифры и обратная ссылка к первому захваченному разделителю
  • (?:\d{4}|\d{2}) Совпадениеeithe 4 или 2 цифры
  • \b Граница слова

Regex demo | Python demo

Например, используя re.finditer (в качестве re.findall будет возвращена группа захвата, которая является разделителем)

import re
reg = r"\b\d{1,2}([./-])\d{1,2}\1(?:\d{4}|\d{2})\b"
s = "01.11.11 12/12/1981 1*51*12 . 22|1|13 03-02-1919 1-22-12 or 01-23-18 or 03-23-1984 01.11.18 or 2.2.17 or 02.02.18 or 12.1.16 12.23.1943 01-23-11 not 12.23.192 not 02.02.1"

matches = re.finditer(reg, s)
for matchNum, match in enumerate(matches, start=1):
    print(match.group())
2 голосов
/ 04 октября 2019

Вместо совпадения . между наборами чисел - которые будут соответствовать любому символу - совпадать только с теми, которые вы ищете;. - /.

Фиксированное регулярное выражение:

\d{1,2}[\.\/-]\d{1,2}[\.\/-](?:\d{4}|\d{2})\b

Также добавляет границу слова в конце, чтобы избежать совпадения дат только с 3-значными годами.

regex101 пример: https://regex101.com/r/0r6jru/2

1 голос
/ 04 октября 2019

\b((?:\d{1,2}(?:\.|\/|-)){2}(?:\d{4}|\d{2}))\b

Это регулярное выражение будет соответствовать всем вашим тестам и отфильтровывает неподходящие годы, такие как 12.23.192

Попробуйте здесь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...