如何在Python中合并重复非字母数字序列并避免误改URL?
重复非字母数字序列的正则替换问题
需求说明
我有一段包含重复非字母数字序列的文本,例如:
abc\n \n def\n \n kk
需要将重复的非字母数字序列(可能包含空格、制表符、换行、逗号等任意非字母符号)仅保留为单个序列,处理后结果如下:
abc\n def\n kk
现有方案的问题
@Barmar提供的正则方案近乎完美,但存在两个问题:
- 对复杂文本(如下方示例)单次替换无法彻底处理所有重复序列:
原输入:
\n \n \n \n \n \n aaa \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n bbb \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n aaa \n \n \n \n \n \xa0May 25, 2023 \n\n \n\n \n \n \n \n \n \n\n \n ttt\n\n \n \n \n Read more \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n tt \n \n\n \xa0•\xa0©\n \n 2023\n \n\n \n \n sss \xa0 eee \n \n \n \n \n \n \n \n \n
单次替换后的结果仍存在未处理的重复序列:
\n aaa \n bbb \n aaa \n \n \xa0May 25, 2023 \n\n \n \n \n \n ttt\n \n \n Read more \n tt \n \n \xa0•\xa0©\n 2023\n \n \n sss \xa0 eee \n
- 处理包含
https://nomads.com这类URL的文本时,会误将双斜杠替换为单斜杠,破坏URL结构。
更新说明
- 重复应用正则表达式可解决单次替换不彻底的问题,直到文本不再变化即可完成全部替换。
- 需要调整方案避免误处理URL中的双斜杠。
解决方案
1. 循环替换解决不彻底问题
通过循环执行正则替换,直到文本不再发生变化,确保所有嵌套或多层重复的非字母数字序列都被处理。
2. 安全处理URL的实现代码
采用临时标记法先保护URL中的双斜杠,处理完成后再恢复,避免误修改:
import re def collapse_repeated_non_alnum(text): # 临时替换URL中的双斜杠,避免被正则修改 temp_slash = '__SAFE_DOUBLE_SLASH__' text = re.sub(r'(https?:)\/\/', r'\1' + temp_slash, text) # 匹配重复的非字母数字序列并替换为单个序列 pattern = re.compile(r'([^a-zA-Z0-9]+)\1+') while True: new_text = pattern.sub(r'\1', text) if new_text == text: break text = new_text # 恢复URL中的双斜杠 text = re.sub(r'(https?:)' + temp_slash, r'\1//', text) return text
代码说明
- 第一步:用临时标记替换
http://和https://中的双斜杠,避免被正则匹配为重复非字母数字序列。 - 第二步:循环执行正则替换,将所有重复的非字母数字序列(单个符号或组合符号的重复)替换为单个序列,直到文本稳定。
- 第三步:将临时标记换回双斜杠,恢复URL的正确格式。
内容的提问来源于stack exchange,提问作者mimic
相关产品推荐
相关产品推荐

