我正在从事一个 NLP 项目,该项目要求我从一段文本中删除计算机代码。代码包含在标签
<pre><code>
和
</code></pre>
之间。现在我可以做一个简单的正则表达式匹配,但我想概括这个函数,以便它可以删除任何两个指定字符串之间的文本,即使它们是嵌套的。
例如,如果我有一个字符串:
string = "<pre><code> Should be deleted <pre><code> also deleted </code></pre> delete this too </code></pre> don't delete <pre><code> delete </code></pre> "
,那么我期望输出为字符串
" don't delete "
如果我这样做
re.sub('(<pre><code>)(.*)(</code></pre>)', '', string)
,它会给我一个空字符串。
我知道如何对单个字符执行此操作,例如删除大括号之间的字符串。例如,如果我的字符串是
string = "{ Should be deleted { also deleted } delete this too } don't delete { delete } "
,那么这样做会给我所需的输出:
a = '{'
b = '}'
regexp = a + '[^' +a + '^' + b + ']*' + b
while a in string or b in string:
string = re.sub(regexp, '', string)
regexp
评估到
'{[^{^}]*}'
此处。 while 循环是必要的,因为像
re.sub(r'{[^{^}]*}', '', string)
这样的解决方案不适用于嵌套情况。
我尝试通过执行
re.sub('(<pre><code>)[^(</code></pre>)^(<pre><code>)](</code></pre>)', '', string)
应用与单字符情况相同的逻辑,但它会产生输出:
"<pre><code> Should be deleted <pre><code> also deleted </code></pre> delete this too </code></pre> don't delete <pre><code> delete </code></pre> "
这意味着没有任何内容匹配。
你几乎做到了!问题在于正则表达式的贪婪匹配行为。让我们将其分解:
-
贪婪匹配:
(.*)
会尽可能多地匹配任何字符(包括换行符),这会导致它匹配第一个<pre><code>
到最后一个</code></pre>
之间的所有内容,包括嵌套的标签。 -
非贪婪匹配: 要解决这个问题,你需要使用非贪婪匹配。在量词(如
*
、+
或?
)后面添加?
可以使其成为非贪婪的。所以,你需要将(.*)
改为(.*?)
。
以下是更新后的代码:
import re
string = "<pre><code> Should be deleted <pre><code> also deleted </code></pre> delete this too </code></pre> don't delete <pre><code> delete </code></pre> "
start_tag = "<pre><code>"
end_tag = "</code></pre>"
regexp = f"{start_tag}(.*?){end_tag}"
result = re.sub(regexp, '', string)
print(result) # 输出: don't delete
解释:
-
(.*?)
现在会匹配尽可能少的字符,直到找到下一个</code></pre>
。 -
f"{start_tag}(.*?){end_tag}"
使用 f-string 动态地创建正则表达式,使其更易于阅读和修改。
现在,代码可以正确地删除两个指定字符串之间的所有内容,即使它们是嵌套的。
标签:python,regex From: 78795570