RegEx Python

From Noah.org
Revision as of 04:29, 7 June 2007 by Root (talk | contribs)
Jump to navigationJump to search

Regular Expressions in Python syntax

Pulling a block of text out of another

The following will find any multiline block of HTML comments that begin with "<!-- EDIT". This can be addaped for anytime you want to pull one chunk of string out of another. Note, don't confuse the fact that we are looking for a multiline block with needing the re.MULTILINE flag. In fact we need the re.DOTALL flag, which we pass using the pattern syntax for flags.

 print re.findall("(?s)<!-- EDIT.*?-->", string)[0]

Compilation Flags -- inline

Python regex flags effect matching. For example: re.MULTILINE, re.IGNORECASE, re.DOTALL. Unfortunately, passing these flags is awkward if want to put regex patterns in a config file or database or otherwise want to have the user be able to enter in regex patterns. You don't want to have to make the user pass in flags separatly. Luckily, you can pass flags in the pattern itself. This is a very poorly documented feature of Python regular expressions. At the start of the pattern add flags like this:

 (?i) for re.IGNORECASE
 (?L) for re.LOCALE (Make \w, \W, \b, \B, \s and \S dependent on the current locale.)
 (?m) for re.MULTILINE  (Makes ^ and $ match before and after newlines)
 (?s) for re.DOTALL  (Makes . match newlines)
 (?u) for re.UNICODE (Make \w, \W, \b, \B, \d, \D, \s and \S dependent on the Unicode character properties database.)
 (?x) for re.VERBOSE

For example, the following pattern ignores case:

 re.search ("(?i)password", string)

The flags can be combined. The following ignores case and matches DOTALL:

 re.search ("(?is)username.*?password", string)

Parse a simple date

This format is used by the `motion` command. This parses the date from filenames in this example format:

   02-20070505085051-04.jpg

The return format is a sequence the same as used in the standard Python library time module. This is pretty trivial, but shows using named sub-expressions.

def date_from_filename (filename):
    m = re.match(".*?[0-9]{2}-(?P<YEAR>[0-9]{4})(?P<MONTH>[0-9]{2})(?P<DAY>[0-9]{2})(?P<HOUR>[0-9]{2})(?P<MIN>[0-9]{2})(?P<SEC>[0-9]{2})-(?P<SEQ>[0-9]{2}).*?", filename)
    if m is None:
        print "Bad date parse in filename:", filename
        return None
    day   = int(m.group('DAY'))
    month = int(m.group('MONTH'))
    year  = int(m.group('YEAR'))
    hour  = int(m.group('HOUR'))
    min   = int(m.group('MIN'))
    sec   = int(m.group('SEC'))
    dts = (year, month, day, hour, min, sec, 0, 1, -1)
    return dts