How to ignore some delimited text when doing Python re.sub

Viewed 54

I'm trying to "parse" some LaTeX code. LaTeX uses some special characters such as %, #, {, } and delimits inline math environments with $ … $.

What I need is to escape (\) all special chars that are not already escaped and are not inside $ … $.

For example, for the provided entry

#s{o}me\%thing $ \text{a} $

I need to return:

\#s\{o\}me\%thing $ \text{a} $

Note that the already escaped \%, as well as the \text{a} within $ … $, remain untouched.

I'm using Python's re.sub to do that, and this way I can ignore the escaped ones, but I don't know how to ignore $ … $ environments. My current code is:

string = "#s{o}me\%thing $ \text{a} $"
re.sub(r'([^\\]?)((?:%|#|{|}|&))', r"\1\\\2", string)
# Expected output: "\#s\{o\}me\%thing $ \text{a} $"
# Actual output:   "\#s\{o\}me\%thing $ \text\{a\} $"

At this time, my code returns, for the example above, the following:

\#s\{o\}me\%thing $ \text\{a\} $

Any suggestions??

1 Answers

You can consider the following solution:

import re
s = r"#s{o}me\%thing $ \text{a} $"
rx = r'(?<!\\)((?:\\{2})*)(?:(\$[^$\\]*(?:\\.[^$\\]*)*\$)|([%#{}&]))'
print ( re.sub(rx, lambda x: fr"{x.group(1)}\{x.group(3)}" if x.group(3) else fr"{x.group(1)}{x.group(2)}", s, flags=re.S) )
# => \#s\{o\}me\%thing $ \text{a} $

See a Python demo

The regex is

(?<!\\)((?:\\{2})*)(?:(\$[^$\\]*(?:\\.[^$\\]*)*\$)|([%#{}&]))

See the regex demo. Details:

  • (?<!\\) - no \ immediately to the left of the current location is allowed
  • ((?:\\{2})*) - Group 1: zero or more sequences of double backslashes
  • (?:(\$[^$\\]*(?:\\.[^$\\]*)*\$)|([%#{}&])) - either of
    • (\$[^$\\]*(?:\\.[^$\\]*)*\$) - Group 2: $, then any zero or more chars other than \ and $, then zero or more occurrences of an escape sequence (\ + any char) and then any zero or more chars other than \ and $, and then a $
    • | - or
    • ([%#{}&]) - Group 3: %, #, {, } or &.

If Group 3 is matched, the match is replaced with Group 1 + \ + Group 3 values, else, the results is a concatenation of Group 1 and Group 2 values.

Related