Skip to content

Instantly share code, notes, and snippets.

@samba
Last active December 13, 2015 17:19
Show Gist options
  • Save samba/4947008 to your computer and use it in GitHub Desktop.
Save samba/4947008 to your computer and use it in GitHub Desktop.
PERL-style RegExp substitution in Python (but within "s/.../.../", uses Python syntax)
#!/usr/bin/env python
# Python support for PERL's shorthand of pattern substitution (s/.../.../)
# Supports flags:
# i => case insensitive
# m => multiline match (caret and dollar represent line terminations, not whole-string)
# s => "dot-all" - dot matches everything, including new-line
# g => "global" - replace every instance (without this, only the first)
import re
sample = "#replace s@ABC(\@2)@\\1DEF@g"
RE_REPLACE_DIRECTIVE = '^#replace\s+(.*)$'
class ReplaceParser(object):
RE_REPLACE_CORE = r'^s([@#%/])((?:\\\1|(?!\1).)*)\1((?:\\\1|(?!\1).)*)\1(\w*)$'
FLAG_REF = {
'i': re.IGNORECASE,
'm': re.MULTILINE,
's': re.DOTALL
}
def __init__(self, replacement):
self.expression = replacement
self.match = re.match(self.RE_REPLACE_CORE, replacement)
self.lookfor = self.match and self.match.group(2)
self.replacewith = self.match and self.match.group(3)
self.flags = self.match and self.match.group(4)
self.bitflags = 0
self.limit = 1
for flag in self.flags:
if flag in self.FLAG_REF:
self.bitflags = self.bitflags | self.FLAG_REF[ flag ]
if flag in ('g'):
self.limit = 0
def __repr__(self):
return repr([ self.expression, self.lookfor, self.replacewith, self.flags ])
def apply(self, string):
return re.sub(self.lookfor, self.replacewith, string, flags = self.bitflags, count = self.limit)
sample = re.sub(RE_REPLACE_DIRECTIVE, r'\1', sample).strip()
handler = ReplaceParser(sample)
print repr(handler)
# ['s@ABC(\\@2)@\\1DEF@g', 'ABC(\\@2)', '\\1DEF', 'g']
print handler.apply("this is ABC@2 test ABC@2 as well")
# this is @2DEF test @2DEF as well
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment