1

In a document, every time the pattern

$$mystring$$

occurs on a single line, I need new lines to be added between the $$s and the string i.e.:

$$
mystring
$$

Here is my attempt

s = "$$mystring1$$ \n $$mystring2$$ \n $$fake"

print(re.sub('\n\$\$.*?\$\$',"\n\\1\n",s))

Should produce:

$$
mystring1
$$
$$
mystring2
$$
$$fake
2

2 Answers 2

1

I understand your $$...$$ pattern must occupy the whole line (with or without leading/trailing whitespaces).

In this case, you do not need a regex, you can use

s = "$$mystring1$$ \n $$mystring2$$ \n $$fake"
output = []
for l in s.splitlines():
    l = l.strip()
    if l.startswith('$$') and l.endswith('$$'):
        output.append('$$\n' + l[2:-2] + '\n$$')
    else:
        output.append(l.strip())

print('\n'.join(output))

See this Python demo. That is, if a line starts and ends with $$, get the line part without the first and last two chars and wrap it with newlines, else, just keep the line as is.

Output:

$$
mystring1
$$
$$
mystring2
$$
$$fake

If you need to break the lines at doubled $$s, you can use something like

import re
s = "$$mystring1$$ \n $$mystring2$$ \n $$fake"
print(re.sub(r'(\$\$)(.*?)(\$\$)', '\\1\n\\2\n\\3', s))

See this Python demo. Output:

$$
mystring1
$$ 
 $$
mystring2
$$ 
 $$fake

The (\$\$)(.*?)(\$\$) matches $$ and captures it into Group 1, then captures into Group 2 any zero or more chars other than line break chars as few as possible, and then captures into Group 3 a $$ substring. The replacement pattern just keeps these groups inserting line feeds between Group 1 and 2 and Group 2 and 3.

1

The pattern \n\$\$.*?\$\$ starts the match with a newline, directly followed by $$

That pattern does not match in $$mystring1$$ \n $$mystring2$$ \n $$fake


Another option could be using 2 capture groups, matching what you don't want and capturing what you want to keep.

In the callback check for the existence of the groups for the replacement.

^\s*(?:\$\$(.*?)\$\$\s*|(\$\$.*))$
  • ^ Start of string
  • \s* Match optional whitspace chars
  • (?: Non capture group for the alternation
    • \$\$(.*?)\$\$\s* Capture any char in between 2 dollar signs in group 1
    • | Or
    • (\$\$.*) capture 2 dollar signs and the rest of the string in group 2
  • ) Close non capture group
  • $ End of string

See s regex demo and a Python demo

import re

pattern = r"^\s*(?:\$\$(.*?)\$\$\s*|(\$\$.*))$"
s = "$$mystring1$$ \n $$mystring2$$ \n $$fake"

result = re.sub(
    pattern,
    lambda x: x.group(2) if x.group(2) else f"$$\n{x.group(1)}\n$$",
    s,
    0,
    re.MULTILINE
)

print(result)

Output

$$
mystring1
$$
$$
mystring2
$$
$$fake

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.