5

I want to transform a text like:

$$
foo
bar
$$

to

<% tex
foo
bar
%>

and $\alpha$ to <% tex \alpha %>.

For the single line replace, I did this:

re.sub(r"\$(.*)\$", r"<% tex \1 %>", text)

...and it works fine.

Now, I added the multiline flag to catch the multiline one:

re.sub(r"(?i)\$\$(.*)\$\$", r"<% tex \1 %>", text)

...but it returns:

<% tex  %>
foo
bar
<% tex  %>

Why? I'm sure it's something trivial, but I can't imagine what.

leoluk
  • 12,561
  • 6
  • 44
  • 51

2 Answers2

12

I'd suggest using the re.M (multiline) flag, and gobbling up everything not a dollar sign in your capture.

>>> import re
>>> t = """$$
foo
bar
$$"""
>>> re.sub(r"\$\$([^\$]+)\$\$", r"<% tex \1 %>", t, re.M)
'<% tex \nfoo\nbar\n %>'
Ryan Ginstrom
  • 13,915
  • 5
  • 45
  • 60
  • 4
    This solution works--and doesn't even need the multiline flag either, since [^\$] includes linebreaks. – twneale Nov 05 '10 at 00:23
  • 2
    The multiline flag is even at the wrong position, since the third argument is `count`. If at all you should do `flag=re.M`. – cronos Feb 26 '16 at 10:55
  • Guys, `re.M` is totally redundant here since it redefines the behavior of `^` and `$` to match start/end of the *line* rather than the whole string. – Wiktor Stribiżew Nov 07 '17 at 09:48
1

With python 2.7.12 I have verified that this will work:

>>> import re
>>> t = """$$
... foo
... bar
... $$"""
>>> re.sub(r"\$\$(.*?)\$\$", r"<% tex \1 %>", t, flags=re.DOTALL)
'<% tex \nfoo\nbar\n %>'

As for the DOTALL flag, according to the official document:

re.S

re.DOTALL

Make the '.' special character matches any character at all, including a newline; without this flag, '.' will match anything except a newline.

Community
  • 1
  • 1