テンプレート内のブロックのこれを識別するための正規表現を探しているので、このブロック全体を置き換えるテキストを提供できます
<div>
{% for link in links %}
textext
{% endfor %}
</div>
そして、このようなものを得る
<div>
mytext
</div>
テンプレート内のブロックのこれを識別するための正規表現を探しているので、このブロック全体を置き換えるテキストを提供できます
<div>
{% for link in links %}
textext
{% endfor %}
</div>
そして、このようなものを得る
<div>
mytext
</div>
残念ながら、ローガンの回答は次の場合には機能しません。
import re
ss1 = '''"Pink Floyd"
<div>
{% for link in links %}
aaaY}eee
12345678
{% endfor %}
</div>
"Fleetwood Mac"'''
pat = '(\{.*)([\w\s]*)(.*)(\})'
print ss1
print '---------------------------'
for el in re.findall(pat,ss1):
print el
print '---------------------------'
print re.sub(pat,':::::',ss1)
結果
"Pink Floyd"
<div>
{% for link in links %}
aaaY}eee # <--------- } here
12345678
{% endfor %}
</div>
"Fleetwood Mac"
---------------------------
('{% for link in links %}', '\n aaaY', '', '}')
('{% endfor %', '', '', '}')
---------------------------
"Pink Floyd"
<div>
:::::eee
12345678
:::::
</div>
"Fleetwood Mac"
.
.
import re
ss2 = '''"Beatles"
<div>
{% for link in links %}
iiiY=uuu # <-------- = here
12345678
{% endfor %}
</div>
"Tino Rossi"'''
pat = '(\{.*)([\w\s]*)(.*)(\})'
print ss2
print '---------------------------'
for el in re.findall(pat,ss2):
print el
print '---------------------------'
print re.sub(pat,':::::',ss2)
結果
"Beatles"
<div>
{% for link in links %}
iiiY=uuu
12345678
{% endfor %}
</div>
"Tino Rossi"
---------------------------
('{% for link in links %', '', '', '}')
('{% endfor %', '', '', '}')
---------------------------
"Beatles"
<div>
:::::
iiiY=uuu
12345678
:::::
</div>
"Tino Rossi"
問題は次のとおりです (私のコードに入れられたfindall()の結果は理解に役立ちます):
最初.*
は、改行に遭遇しない限り実行されます。
次に[\w\s]*
、これらのカテゴリの文字が存在する限り実行されます: 文字、数字、アンダースコア、空白。
空白の中には改行があり、[\w\s]*
1 つの行から次の行に渡って実行できます。
しかし、これらのカテゴリにない文字が によって検出される[\w\s]*
と、この文字で停止します。
の場合、この の前}
の最後の.*
一致 。
次に、正規表現は次の一致を検索します。''
}
の場合、次の改行を渡すことができないため=
、最後.*
に到達する前にテキストのスイートと一致できません。}
したがって、テキスト内の a とは異なる結果}
になります。
.
上記のコードで withに置き換えるとわかるように、 .*
withに.+
置き換えても何も変わりません。.*
.+
.
.
私の解決策
このコードでパターンを提案します:
import re
pat = ('\{%[^\r\n]+%\}'
'.+?'
'\{%[^\r\n]+%\}')
ss = '''"Pink Floyd"
<div>
{% for link in links %}
aaaY}eee
12345678
{% endfor %}
</div>
"Fleetwood Mac"
"Beth Hart"
"Jimmy Cliff"
"Led Zepelin"
Beatles"
<div>
{% for link in links %}
iiiY=uuu
12345678
{% endfor %}
</div>
"Tino Rossi"'''
print '\n',ss,'\n\n---------------------------\n'
print re.sub(pat,':::::',ss,flags=re.DOTALL)
その結果
"Pink Floyd"
<div>
{% for link in links %}
aaaY}eee
12345678
{% endfor %}
</div>
"Fleetwood Mac"
"Beth Hart"
"Jimmy Cliff"
"Led Zepelin"
Beatles"
<div>
{% for link in links %}
iiiY=uuu
12345678
{% endfor %}
</div>
"Tino Rossi"
---------------------------
"Pink Floyd"
<div>
:::::
</div>
"Fleetwood Mac"
"Beth Hart"
"Jimmy Cliff"
"Led Zepelin"
Beatles"
<div>
:::::
</div>
"Tino Rossi"
編集
より簡単:
pat = ('\{%[^}]+%\}'
'.+?'
'\{%[^}]+%\}')
{%.....%}
リーニュに記号が含まれていない場合のみ}
試す:
re.sub('\{.*[\w\s]*.*\}','mytext',txt)
出力:
'<div>\n mytext\n</div>'
\{
は最初のブレースに.*[\w\s]*.*
一致し、次に最後のブレースまでの残りすべて (空白と改行を含む) に一致します\}
。
次のようなものでより具体的にすることができます:
re.sub('\{% for link in links.*[\w\s]*.*end for %\}','mytext',txt)
指定したタイプの for ループにのみ一致することを確認できます。
編集: eyquem は、特に真ん中に記号がある場合、多くの場合、私の答えが不十分であることを指摘しました。なぜ私のソリューションがうまくいかなかったのかを素朴に誤解する危険を冒して、彼のテストケースにもうまくマッチするパターンに余分なビットを追加しただけなので、それがうまくいくかどうか見てみましょう:
re.sub('\{.*[\W\w\s]*.*\}', 'mytext', txt)
結果(txt
eyquemsのピンクフロイドの例はどこにありますか):
"Pink Floyd"
<div>
mytext
</div>
"Fleetwood Mac"
したがって、英数字以外のすべての記号を追加すると修正されると思います。または、別のケースでさらに明らかにそれを壊した可能性があります。きっと誰かが指摘してくれるでしょう。:)'
EDIT2:ページに複数のループがある場合、両方のソリューションが失敗することにも注意しfor
てください。例:
"Beatles"
<div>
{% for link in links %}
iiiY=uuu
12345678
{% endfor %}
</div>
"Tino Rossi"
{ for link in links % }
asdfasdfas
{% endfor% }
収量
"Beatles"
<div>
mytext
そして、 .
編集 2: eyquem は、後に 1 つある場合は切り取らないように彼を修正することで再び正しいです。彼の修正は私のものも修正します:
re.sub('\{.*[\W\w\s]*?.*\}', 'mytext', txt)
が新しいパターンです。
大ハンマーのアプローチは次のようになります。
In [540]: txt = """<div>
{% for link in links %}
textext
{% endfor %}
</div>"""
In [541]: txt
Out[541]: '<div>\n {% for link in links %}\n textext\n {% endfor %}\n</div>'
In [542]: re.sub("(?s)<div>.*?</div>", "<div>mytext</div>", txt)
Out[542]: '<div>mytext</div>'