модификация, делающая регулярное выражение более специфичным для исключения определенных символов - PullRequest
2 голосов
/ 07 октября 2019
import re
s = '01.20/15 01/20.1915 1/1/19 01.11.11 1.8-24 3-4.12 01/20-09 12/12/1981 12-01/2001 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, которая является модификацией , что делает регулярное выражение более конкретным для исключения определенных символов

Я хочу получить все даты, поэтому я использую

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

и я получаю

['01.20/15',
 '01/20.1915',
 '1/1/19',
 '01.11.11',
 '1.8-24',
 '3-4.12',
 '01/20-09',
 '12/12/1981',
 '12-01/2001',
 '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']

Это близко к тому, что я хочу, но я не хочу строки, которые имеют сочетание . или / или - например '01.20/15' или '3-4.12' или 3-4.12 и т. Д.

Мой желаемый вывод - это

['1/1/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']

, который не содержит чисел, которые имеют сочетание . или / или- например '01.20/15' или '3-4.12'

Я также пытался изменить reg

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

, но это не совсем работает

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

Ответы [ 3 ]

3 голосов
/ 07 октября 2019

Можно использовать findall () с одной группой захвата вместо использования обратного ссылки, например,

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

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

Расширенное

 \b 
 (                             # (1 start)
      (?:
           \d{1,2} \. \d{1,2} \. 
        |  
           \d{1,2} / \d{1,2} /
        |  
           \d{1,2} - \d{1,2} -
      )
      (?: \d{2} | \d{4} )
 )                             # (1 end)
 \b
3 голосов
/ 07 октября 2019

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

\b([0-9]{1,2}([./-])[0-9]{1,2}\2[0-9]{2,4})\b

или

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

Демо

Тест

import re

regex = r'\b([0-9]{1,2}([./-])[0-9]{1,2}\2\d{2,4})\b'
string = '''
01.20/15 01/20.1915  01.11.11 1.8-24 3-4.12 01/20-09 12/12/1981 12-01/2001 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.findall(regex, string)

output = []
for match in matches:
    output.append(match[0])

print(output)

Выход

['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.192']

Демо

0 голосов
/ 07 октября 2019

Это может приблизить вас к тому, что вы ищете:

RE = r'((?:\d{1,2}(?:\.|\/|-)){2}\d{1,4})'

Это будет соответствовать большинству введенных данных, за исключением следующих строк:

11-11-12-13-15.1645
01-01-11-12

Это регулярное выражение будет захватывать 11-11-12 и 13-15.1645 для первого примера и 01-01-11 для второго. Вы можете выполнить некоторую предварительную обработку более длинных строк, чтобы разделить их на разделители - | / | .. Разделив первый разделитель, затем второй, ... пока не найдете совпадение с помощью re.match(post_split[0]) и re.match(post_split[1]).

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