Absence of leading or trailing space in regex invalidates search

Viewed 29

I am trying to search different types of dates in my strings using regex.

import re

txt1 = "The date is 3-Dec "
txt2 = "The date is3-Dec "
txt3 = "The date is 3-Dec"
txt4 = "The date is Dec-20"
txt5 = "The date isDec-20"

regx = r"(?:\d{2}|\d{1}|\d{0})(?:[,| ,|, |-|/|\\|\s|\d{0}])(?:%s)(?:[,| ,|, |-|/|\\|\s|\d{0}])(?:\d{4}|\d{2}|\d{0})" % '|'.join(['Nov', 'Dec'])

x1 = re.findall(regx, txt1)
print(x1)
x2 = re.findall(regx, txt2)
print(x2)
x3 = re.findall(regx, txt3)
print(x3) # empty
x4 = re.findall(regx, txt4)
print(x4)
x5 = re.findall(regx, txt5)
print(x5) # empty

Could someone help why txt3 and txt5 are not working? Basically following portion of regex is not working when there is no leading or trailing space for date (?:[,| ,|, |-|/|\\|\s|\d{0}])

1 Answers

You can use

months = ['Nov', 'Dec']
date_rx = r'(?:[1-9]|[12]\d|3[01])'
month_rx = r'(?:{})'.format('|'.join(months))
sep_rx = r'[\s,/\\-]'
regx = r"(?<!\d){0}{2}{1}|{1}{2}{0}(?!\d)".format(date_rx, month_rx, sep_rx)

See the online Python demo. The regex is

(?<!\d)(?:[1-9]|[12]\d|3[01])[\s,/\\-](?:Nov|Dec)|(?:Nov|Dec)[\s,/\\-](?:[1-9]|[12]\d|3[01])(?!\d)

See the regex demo.

Regex part details:

  • (?:[1-9]|[12]\d|3[01]) (date_rx) - a non-zero digit, 10 to 29 or 30 or 31
  • (?:Nov|Dec) (month_rx) - Nov or Dec
  • [\s,/\\-] (sep_rx) - whitespace, comma, slash, backslash or a hyphen.

The negative lookbehind (?<!\d) makes sure there is no digit immediately to the left of the current location and the negative lookahead (?!\d) makes sure there is no digit immediately to the right of the current location.

Related