Regex - найти шаблон даты в строке - PullRequest
1 голос
/ 25 марта 2020

Я борюсь с python регулярным выражением, чувствуя, что моя проблема проста, но я застрял. Я пытаюсь идентифицировать подстроку даты в строгом формате YYYY-MM-DD внутри строки. Достаточно просто. Но я хочу быть уверен, что регулярное выражение не обнаруживает ложноположительных результатов. Некоторые примеры исходной строки, которые мне нужно продолжить:

string1='foo2012-09-2018-09-03foo'
string2='2012-09-2018-09-03'

Я хочу извлечь строку, представляющую строку даты 2018-09-03 и , а не эту строку 2012-09-20. Я пробовал различные картины. Basi c один что-то вроде:

import re
string1='foo2012-09-2018-09-03foo'
string2='2012-09-2018-09-03'
pattern  = '[\d]{4}[-_.][\d]{2}[-_.][0-3][\d]'
for match in re.finditer(pattern, string1):
    print(match)
    # FAIL : <re.Match object; span=(3, 13), match='2012-09-20'>
for match in re.finditer(pattern, string2):
    print(match)
    # FAIL : <re.Match object; span=(0, 10), match='2012-09-20'>

Хорошо, не работает, давайте изменим шаблон, чтобы проверить, если предыдущий и следующий символ не ди git:

pattern  = '[\D][\d]{4}[-_.][\d]{2}[-_.][0-3][\d][\D]'
for match in re.finditer(pattern, string1):
    i, j = match.span()
    if string1[i] not in '0123456789': i+=1
    if string1[j] not in '0123456789': j-=1
    print(string1[i:j])
    # SUCCESS : 2018-09-03 
for match in re.finditer(pattern, string2):
    i, j = match.span()
    if string2[i] not in '0123456789': i+=1
    if string2[j] not in '0123456789': j-=1
    print(string2[i:j])
    # FAIL : no match !

Второй не работает, потому что в string2 нет символа после подстроки, которую я ищу. Есть ли способ изменить шаблон так, чтобы он искал дату, за которой следовал бы не десятичный ди git или конец строки?

PS: первое сообщение!

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

Пример, если это поможет ...

import re

#using a list as output can then be looped for this example
strings = ['foo2012-09-2018-09-03foo', '2012-09-2018-09-03']

#Is there a way to adjust the pattern to say look for date followed by a non decimal digit or end of the string?
#Yes! :o) Use a non-capturing group for 'not a number or the end of the line' which is: (?:\D|$)
pattern = re.compile(r'(\d{4}-\d{2}-\d{2})(?:\D|$)')

for string in strings:
    print(pattern.search(string)[1])

for string in strings:
    print(pattern.findall(string))

Выходы:

2018-09-03
2018-09-03
['2018-09-03']
['2018-09-03']
0 голосов
/ 26 марта 2020

Благодаря Джоанис , ответ отрицательный:

import re
pattern  = '(?<!\d)\d{4}[-_.]\d{2}[-_.][0-3]\d(?!\d)'
string1='foo2012-09-2018-09-03foo'
for match in re.finditer(pattern, string1):
    i, j = match.span()
    print(string1[i:j])
    # WORK : 2018-09-03

string2='2012-09-2018-09-03'
for match in re.finditer(pattern, string2):
    i, j = match.span()
    print(string2[i:j])
    # WORK : 2018-09-03
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...