如何避免Python正则表达式匹配单词子串?
解决正则误匹配子串的问题
正确代码实现
import re def add_atsign(sents): for i, sent in enumerate(sents): # 用零宽断言定位独立单词,避免误匹配子串或捕获空格 sents[i] = re.sub(r'(?<=^|\s)([a-zA-Z0-9_]{4,15})(?=\s|$)', r'@\1', str(sent)) return sents
测试效果
运行以下代码:
mylist = ["ali_s ali_t ali_u aabs:/t.co/kMMALke2l9"] print(add_atsign(mylist))
得到预期结果:
['@ali_s @ali_t @ali_u aabs:/t.co/kMMALke2l9']
为什么之前的写法不对?
- 第一版正则
r'([a-zA-Z0-9_]{4,15})'没有边界限制,只要是长度符合的子串就会被匹配——比如aabs:/里的aabs、kMMALke2l9都被误加了@。 - 第二版正则
r'((^|\s)[a-zA-Z0-9_]{4,15}(\s|$))'把前后的空格也包含进了捕获组,替换时@\1会把空格+单词+空格变成@空格+单词+空格,导致空格位置错乱(比如出现ali_t@这种错误格式)。
正则逻辑说明
(?<=^|\s):反向零宽断言,只检查目标单词前面是字符串开头或者空格,不把这个空格捕获进来。([a-zA-Z0-9_]{4,15}):捕获我们真正要处理的单词——长度4到15位,由字母、数字、下划线组成。(?=\s|$):正向零宽断言,检查目标单词后面是空格或者字符串结尾,同样不捕获这个空格。
这样替换时只会给独立的目标单词加上@,既不会碰那些和其他符号连在一起的子串,也不会打乱原来的空格布局。
内容的提问来源于stack exchange,提问作者HosseinSedghian
相关产品推荐
相关产品推荐

