python用regexp替换字符串

python用regexp替换字符串,python,Python,我正在寻找一个regexp来标识模板中的这个for块,这样我就可以提供文本来替换整个块 <div> {% for link in links %} textext {% endfor %} </div> {%用于链接中的链接%} 文本 {%endfor%} 得到这样的东西 <div> mytext </div> 我的文本 大锤式方法是: In [540]: txt = """<div> {% for link

我正在寻找一个regexp来标识模板中的这个for块,这样我就可以提供文本来替换整个块

<div>
 {% for link in links %}
     textext
 {% endfor %}
</div>

{%用于链接中的链接%}
文本
{%endfor%}
得到这样的东西

<div>
 mytext
</div>

我的文本

大锤式方法是:

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>'
[540]中的
:txt=“”
{%用于链接中的链接%}
文本
{%endfor%}
"""
In[541]:txt
Out[541]:“\n{%for links%}\n textext\n{%endfor%}\n”
在[542]中:re.sub(“(?s.*?”,“mytext”,txt)
Out[542]:“mytext”
试试:

输出:

'<div>\n mytext\n</div>'
然后您可以确定它将只匹配您指定类型的for循环

编辑:艾奎姆指出,我的回答在很多情况下是不够的,特别是在中间有符号的情况下。冒着天真地误解为什么我的解决方案不起作用的风险,我只是在我的模式中添加了一个额外的位,它甚至成功地匹配了他的测试用例,所以我们将看看它是否起作用:

re.sub('\{.*[\W\w\s]*.*\}', 'mytext', txt)
结果(其中
txt
是eyquems的Pink Floyd示例):

屈服

"Beatles"
<div>
 mytext

是新模式。

我很遗憾地说,洛根的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
    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"

只有当对齐的
{%..…%}
不包含符号
}

时,我才尝试了这个re.sub(“{%用于链接%}.{%endfor%}”、“mytest”、“stringHTML”)@Zed您所说的尝试几乎是正确的。只需在
*
之后添加
,即可取消正则表达式的reedy,并将标记
re.DOTALL
放置,以使点能够匹配换行符
\n
-现在,您应该看看我的解决方案,在其中我使用<代码> [^ \r\n] < /代码>以获得一个符号,它仍然不匹配行的结尾,即使在DOOLT上下文中,因此将正则表达式推广到不同形式的块<代码> {%…%} /代码> -最后,您应该考虑洛根的答案是否真的应该被接受。我敢说我不认为是sothanks,但我的错误是我没有说,有时block会有div,有时不会,我不知道这就是为什么在这类事情上使用regexp通常是个坏主意。使用
lxml
或其他解析器将是一个更好的主意,因为您可以缩小使用Xpath的范围。告诉过你那是一把大锤,你需要一把手术刀。Xml/Html是结构化文档是有原因的。@sotapme我不知道正则表达式模式中的符号
(?s)
。我尝试过代码,我知道它相当于标志re.DOTALL。但是我从未在Python文档中看到过任何关于这个
(?s)
的信息。它不属于Python3,只是因为它在我的Python2代码中起作用。我在哪里可以找到提供这方面信息的文档?搜索(?iLmsux)@sotapme…aaaaaaah。。。哎哟!!非常感谢。在我学习正则表达式的第一次阅读时,我还没有理解它,然后我再也没有在博士的这一点上停下来。好吧,那很不幸(虽然回答得很好!我不想把它弄得太复杂(lazy:)),但我想这一次没有解决问题。@Logan我可以在OP上发表评论,告诉他我的答案吗?风险在于你,他会改变他对答案的接受。好吧,我本来打算自己做的,只是我想我修正了我的答案。我要更新我的,让我们看看你的想法。@Logan我也更新了我的:我用
'.+'
替换了
'.+?'
,效果非常好老实说,我觉得我们的解决方案太相似了。归根结底,这取决于使用哪种表达式的偏好。你的修复也修复了我的修复。您匹配for循环的整个开始和整个结束标记,而我只是分别匹配每个循环的第一个和最后一个大括号。@Logan@Zed我更新了我的解决方案(要做的最小更改是:在
'.+'
之后添加一个
符号以使regex ungreedy),现在它工作得非常好,没有Logan的缺陷,抱歉。@Logan不,当在
{%for link in links%}
{%endfor%}
之间的块中放置了符号
{%code>}
时,它仍然不起作用。您应该使用模式中的组执行,以查看它的功能:
'(\{.*)([\W\W\s]*?)(.*\})
"Beatles"
<div>
 {% for link in links %}
    iiiY=uuu
    12345678
 {% endfor %}
</div>
"Tino Rossi"
{ for link in links % }
   asdfasdfas
{% endfor% }
"Beatles"
<div>
 mytext
re.sub('\{.*[\W\w\s]*?.*\}', 'mytext', txt)
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"
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 = ('\{%[^}]+%\}'
       '.+?'
       '\{%[^}]+%\}')