繁体   English   中英

我可以使用正则表达式替换字符串中的所有关键字吗? (Python)

[英]Can I use regex to replace all keywords in a string? (Python)

这是我的代码:


# case 1
content = "staging_datastorage"
query_term = "st ta ag"

# case 2
# content = "game_event"
# query_term = "gam ame"

terms = re.findall('[a-z0-9]+', query_term, re.I)
terms.sort(key=len, reverse=True)
term_regex = "|".join(terms)
replace_content = re.sub(rf"({term_regex})", r'<em>\1</em>', content, flags = re.I)
print(replace_content)

我想要做的是使用<em> HTML 标记用我的输入字符串( query_term )突出显示表(称为content )中的一些关键字。 输入字符串包含我要突出显示并用空格分隔的关键字。

对于这两种情况,我想要的结果是:

case 1:
this is better
<em>stag</em>ing_da<em>tast</em>or<em>ag</em>e
this is also fine(nesting highlight tag): 
<em>s<em>t<em></em>a</em>g</em>ing_da<em>ta<em></em>st</em>or<em>ag</em>e

case 2:
perfect result: 
<em>game</em>_event
fine result: 
<em>g<em>am</em>e</em>_event

我的代码有一个错误:对于案例 2,它只突出显示gam而不是nam ,这个结果是不正确的: <em>gam</em>e_event

我认为这种情况有点复杂,一个关键字嵌套在另一个关键字中,或者一个关键字是另一个关键字的开始(或结束)部分。

我可以使用正则表达式来解决这个问题吗?

正如我在评论中所说,搜索是不重叠的,下一个找到的是剩余部分。

你可以做什么想法#1

在循环中分别重新re.sub每个关键字。

当然,如果搜索重叠,您可能已经有一些<em></em>阻碍 - 就像这里, ame不会匹配am</em>e - 所以您需要修改单关键字正则表达式. 包括(?:</?em>)? 字母之间。

terms = re.findall('[a-z0-9]+', query_term, re.I)
terms.sort(key=len, reverse=True)
replace_content = content
for term in terms:
    term_regex = "(?:</?em>)?".join(term)
    replace_content = re.sub(rf"({term_regex})", r'<em>\1</em>', replace_content, flags = re.I)

print(replace_content)

两种情况的结果:

<em>s<em>t</em><em>a</em>g</em>ing_da<em>ta</em><em>st</em>or<em>ag</em>e
<em>g<em>am</em>e</em>_event

想法#2

您可以对关键字本身进行预处理,找出哪些前缀与后缀匹配,然后将它们合并到另一个关键字中。

此处: gam有后缀amame有前缀am -> 您将game添加到您的条款中。

这个想法会给出“完美的结果”


想法#3*

做第一个想法,删除嵌套的高光并合并那些彼此相邻的(即删除</em><em> )。

这个想法也会给出“完美的结果”。

要删除一层嵌套,请执行以下操作:

re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", replace_content, flags = re.I)

正则表达式的工作原理是按<em> <em> </em> </em> (如此嵌套)的顺序查找标签,其中包含任何字符组,它们之间没有/ (确保我们只采用最近的结束标签)。

显然,只删除了一层嵌套,我们也需要在循环中使用它 - 这将是一个while循环:while replaces 与上次不同,replace again = 当 replace 不再进行更改时停止。

final_result = ""
while final_result != replace_content:
    final_result = replace_content
    replace_content = re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", final_result, flags = re.I)

print(final_result)

Case2 只需要一个替换,所以让我们看看它在 case1 上是如何工作的:

<em>stag</em>ing_da<em>ta</em><em>st</em>or<em>ag</em>e

现在这只需要删除</em><em> ,正如我提到的!

最后一段代码放在想法 #1 代码之后:

final_result = ""
while final_result != replace_content:
    final_result = replace_content
    replace_content = re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", final_result, flags = re.I)

final_result = final_result.replace("</em><em>", "")
print(final_result)

给出:

<em>stag</em>ing_da<em>tast</em>or<em>ag</em>e

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM