29

I am using the following regex to match different patterns of dates. it works fine in regex101.com. But when I import to python i am getting "bad character range" exception.

  pattern = ur"((?:\b((?:(january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)['\s\.]{0,4}(?:\d{4}|\d{2})|(?:january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)|((?:0[1-9]|[1-3][0-9]|[0-9])/(?:0[1-9]|[1-3][0-9])/(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9]))|((?:0[1-9]|1[0-2]|[1-9])\s{0,3}[-/']{1,3}[\s-/']{0,3}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))))(?:(?![\r\n])\s){0,4})[-/–to]{0,2}(?:(?![\r\n])\s){0,4}(((?:january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)[-'\s\.]{0,4}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))|((?:0[1-9]|[1-3][0-9]|[1-9])/(?:0[1-9]|[1-3][0-9])/(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))|((?:0[1-9]|1[0-2]|[1-9])\s{0,3}[-/']{1,3}[\s-/']{0,3}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9]))))))"

  https://regex101.com/r/rU3cE9/1
user3116355
  • 1,187
  • 3
  • 14
  • 17

1 Answers1

56

Problem is mainly because of the hyphen present inside [\s-/'] character class, therefore Python interprets it as a character interval (like in [a-z]). I suggest you to put the hyphen at the first or at the last position inside the character class [-\s/'] or escape it, to prevent ambiguity.

>>> reg = re.compile(ur"((?:\b((?:(january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)['\s\.]{0,4}(?:\d{4}|\d{2})|(?:january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)|((?:0[1-9]|[1-3][0-9]|[0-9])/(?:0[1-9]|[1-3][0-9])/(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9]))|((?:0[1-9]|1[0-2]|[1-9])\s{0,3}[-/']{1,3}[-\s/']{0,3}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))))(?:(?![\r\n])\s){0,4})[-/to–]{0,2}(?:(?![\r\n])\s){0,4}(((?:january|jan|february|feb|march|mar|april|apr|may|jun|june|july|jul|august|aug|september|set|sep|october|oct|november|nov|december|dec)[-'\s\.]{0,4}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))|((?:0[1-9]|[1-3][0-9]|[1-9])/(?:0[1-9]|[1-3][0-9])/(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9])))|((?:0[1-9]|1[0-2]|[1-9])\s{0,3}[-/']{1,3}[-\s/']{0,3}(?:(19[7-9][0-9])|(20[0-1][0-9])|([7-9][0-9]|[0-1][0-9]))))))")
>>> 
handras
  • 1,548
  • 14
  • 28
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • I got this. But one doubt. Some other expressions here had same type of hyphen, and that was even not at the end. But only this one seem to be caused an error. – user3116355 Feb 16 '15 at 10:39
  • i think it's because , of `\s` (matches any vertical or horizontal space character). So re module failed to find a range between multiple chars and a forward slash. `re` module is designed like that. – Avinash Raj Feb 16 '15 at 10:52
  • Thanks man. Thanks that you find time to share knowledge and info. – user3116355 Feb 16 '15 at 11:05
  • 1
    So what is the hyphen doing here. i.e. Why does it need to be at the beginning or end of the string? – Travis May 15 '15 at 20:07
  • 6
    @Travis A hyphen is used in regexes (specifically inside `[]` in regexes) to denotes a character range, e.g. `[a-z]` denotes any lowercase alphabetic character. In this case, `[\s-/']` is not a character range, so Python complains that it is a "bad character range". Putting the hyphen at the beginning or end (or escaping it) makes Python not interpret it as a character range. – ShreevatsaR Nov 22 '16 at 03:20