How to replace a pattern start with {| to end of string (multi line), if there is no |} inside
<p>What I need is to manipulate bad-formated wiki code.
I have:</p>

<pre><code>s = '''
whatever...
{|
line1
|}

whatever...
{|
lineXXX

'''
</code></pre>

<p>Now I want to delete from {| to end, if no |} inside.</p>

<p>The result I want is:</p>

<pre><code>'''
whatever...
{|
line1
|}

whatever...

'''
</code></pre>

<p>I tried:</p>

<pre><code>re.sub('{|[^(\|\})]*$', '\n',s)
</code></pre>

<p>but failed.</p>

<p>How to do this?</p>

<p>First of all, your pattern contains an unescaped <code>|</code> that becomes an alternation operator. Then, <code>[^(\|\})]*</code> does not negate a <em>sequence</em> of <code>|}</code>, it just matches 0+ chars other than <code>(</code>, <code>|</code>, <code>}</code> and <code>)</code>.</p>

<p>You may use a <a href="http://www.rexegg.com/regex-quantifiers.html#tempered_greed" rel="nofollow"><strong>tempered greedy token</strong></a> (requiring a <code>re.DOTALL</code> modifier):</p>

<pre><code>{\|(?:(?!\|}).)*$
</code></pre>

<p>or its unroll-the-loop variant (not requiring the <code>re.DOTALL</code> modifier):</p>

<pre><code>{\|[^|]*(?:\|(?!})[^|]*)*$
</code></pre>

<p>See <a href="https://regex101.com/r/zY3bC5/3" rel="nofollow">the regex demo</a> or <a href="https://regex101.com/r/zY3bC5/4" rel="nofollow">this one</a>.</p>

<p><strong>Pattern details</strong>:</p>

<ul>
<li><code>{\|</code> - a literal <code>{|</code> text</li>
<li><code>(?:(?!\|}).)*</code> - a tempered greedy token that matches any character (<code>.</code>) that does not start a <code>|}</code> sequence (OR the unrolled variant is <code>[^|]*(?:\|(?!})[^|]*)*</code> - 0+ non-<code>|</code>s followed with 0+ sequences of <code>|</code> not followed with <code>}</code> and then 0+ non-<code>|</code>s)</li>
<li><code>$</code> - end of string.</li>
</ul>

<p>See the <a href="https://ideone.com/Ai3C9v" rel="nofollow">Python demo</a>:</p>

<pre><code>import re
s = '''
whatever...
{|
line1
|}

whatever...
{|
lineXXX

'''
res = re.sub(r'{\|(?:(?!\|}).)*$', '', s, flags=re.S)
print(res)
</code></pre>

python regex