我正在寻找一个正则表达式来标识模板中的这一块,这样我就可以提供文本来替换整个块
<div>
{% for link in links %}
textext
{% endfor %}
</div>然后得到像这样的东西
<div>
mytext
</div>发布于 2013-02-12 02:24:39
尝试:
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示例):
"Pink Floyd"
<div>
mytext
</div>
"Fleetwood Mac"因此,我认为所有非字母数字符号的添加可以修复它。或者我可能在另一个案例中更明显地破坏了它。我相信会有人指出这一点的。:)‘
EDIT2:还应该注意的是,当页面上有多个for-loop时,我们的两个解决方案都会失败。示例:
"Beatles"
<div>
{% for link in links %}
iiiY=uuu
12345678
{% endfor %}
</div>
"Tino Rossi"
{ for link in links % }
asdfasdfas
{% endfor% }收益率
"Beatles"
<div>
mytext然后通过匹配后面的下一组来剔除剩下的部分。
编辑2: eyquem再次正确地修复了他的,如果后面有一个的话就不会被剪掉。他的解决方案也解决了我的问题:
re.sub('\{.*[\W\w\s]*?.*\}', 'mytext', txt)是新的模式。
发布于 2013-02-12 06:22:18
我很遗憾地说,Logan的anwer在以下情况下不起作用:
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]*可以从一行运行到下一行。
但是,如果[\w\s]*遇到不在这些类别中的字符,它会停在这个字符上。
如果是},则最后一个.*与此}之前的''匹配。
然后正则表达式搜索下一个匹配项。
如果它是一个=,则最后一个.*在到达下一个}之前不能匹配文本套件,因为它不能传递下一个换行符。因此,结果与文本中的}不同。
。
将.*替换为.+不会更改任何内容,因为在上面的代码中将.*替换为.+将会看到这一点。
。
。
我的解决方案
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 = ('\{%[^}]+%\}'
'.+?'
'\{%[^}]+%\}')仅当lignes {%.....%}不包含signe }时
发布于 2013-02-12 02:21:59
大锤方法是:
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>'https://stackoverflow.com/questions/14818224
复制相似问题