Je regrette de dire que la anwer de Logan ne fonctionne pas dans les cas suivants:
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)
RÉSULTAT
"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)
RÉSULTAT
"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"
Le problème est le suivant (les résultats de findall() mis à mon aide de code à comprendre):
Les premiers .*
runs aussi longtemps qu'il doesn 't rencontre une nouvelle ligne.
Puis [\w\s]*
s'exécute tant qu'il y a des caractères de ces catégories: lettres, chiffres, trait de soulignement, espaces blancs.
Parmi les espaces sont les retours à la ligne, alors [\w\s]*
peut passer d'une ligne à l'autre.
Mais si un caractère ne se trouvant pas dans ces catégories est rencontré par [\w\s]*
, il s'arrête à ce caractère.
S'il s'agit d'un }
, le dernier .*
correspond à ''
avant cela }
.
Ensuite, la regex cherche le prochain match.
S'il s'agit d'un =
, le dernier .*
ne peut pas correspondre à la suite du texte avant d'atteindre le }
suivant, car il ne peut pas passer le saut de ligne suivant. D'où le résultat différent qu'avec un }
dans le texte.
.
Remplacement .*
avec .+
ne change rien car il sera vu par le remplacement .*
avec .+
dans les codes ci-dessus.
.
.
Ma solution
Je propose la Patern dans ce code:
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)
entraînant
"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"
EDIT
Simpler:
pat = ('\{%[^}]+%\}'
'.+?'
'\{%[^}]+%\}')
que si les lignes {%.....%}
ne contiennent pas le signe }
J'ai essayé re.sub ('{% pour le lien dans les liens%}.* {% endfor%} ',' mytest ', stringHTML) – Zed
@Zed Ce que vous avez dit avoir essayé était presque le bon. Il suffisait d'ajouter un ''? '' Après '. *' Pour rendre l'expression rationnelle non répréhensible, et de placer le drapeau 're.DOTALL' pour que le point puisse correspondre aux nouvelles lignes' '\ n''. - Maintenant, vous devriez regarder ma solution, dans laquelle j'ai utilisé '' [^ \ r \ n] '' pour obtenir un symbole qui ne correspond toujours pas aux extrémités des lignes même dans un contexte DOTALL, généralisant ainsi l'expression rationnelle à varié forme de blocs '' {% ....%} '' - Enfin, vous devriez considérer si la réponse de Logan mérite vraiment d'être acceptée. J'ose dire que je ne le pense pas – eyquem