[英]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
有后缀am
, ame
有前缀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.