如何在Django与Python中基于正则实现指定内容不转小写?
需求与代码修正
现有s_lower方法,原逻辑为所有文本转小写,但匹配到链接的部分保持原样。需复用该逻辑,实现除[spec ...]格式特殊标签内的文本外,其余内容均转小写的功能。
原链接处理代码
RE_WEBURL_NC = ( r"(?:(?:(?:(?:https?):)//)(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[" r"6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?" r":[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9][a-z0-9_-]{0,62})?[a-z0-9]\.)+(?:[a-z]{2,}\.?))(?::\d{2,5})?)(?:" r"(?:[/?#](?:(?![\s\"<>{}|\\^~\[\]`])(?!&lt;|&gt;|&quot;|&#x27;).)*))?" ) def s_lower(value): url_nc = re.compile(f"({RE_WEBURL_NC})") # Do not lowercase links if url_nc.search(value): substrings = url_nc.split(value) for idx, substr in enumerate(substrings): if not url_nc.match(substr): substrings[idx] = i18n_lower(substr) return "".join(substrings) return i18n_lower(value)
初始尝试的特殊标签处理代码
def s_lower(value): spec_nc = re.compile(r"\[spec .*\]") # 匹配[spec some raNdoM cAsE text here]格式的标签 if spec_nc.search(value): substrings = spec_nc.split(value) for idx, substr in enumerate(substrings): if not spec_nc.match(substr): substrings[idx] = i18n_lower(substr) return "".join(substrings) return i18n_lower(value)
问题与修正方案
你的初始代码存在两个核心问题:
- 贪婪匹配导致多标签错误:
.*是贪婪匹配,若文本中有多个[spec ...]标签,会从第一个[spec匹配到最后一个],把中间所有内容都包含进单个标签,破坏逻辑。 - 缺少捕获组导致标签丢失:原链接代码的正则包含捕获组
(),使用split时会保留匹配到的链接作为独立元素;而你的正则没有捕获组,split后会直接移除[spec ...]标签,无法保留原内容。
修正后的代码:
def s_lower(value): # 非贪婪匹配+捕获组,确保单个标签独立匹配,且split后保留标签内容 spec_nc = re.compile(r"(\[spec .*?\])") substrings = spec_nc.split(value) for idx, substr in enumerate(substrings): # 仅对非[spec ...]的内容转小写 if not spec_nc.fullmatch(substr): substrings[idx] = i18n_lower(substr) return "".join(substrings)
关键优化点:
- 正则
(\[spec .*?\]):()捕获组让split保留标签元素;.*?非贪婪匹配,遇到第一个]就停止,保证多标签场景下的正确性。 - 使用
fullmatch替换match:确保只有完全匹配[spec ...]格式的内容才跳过转小写,避免部分匹配的误判。 - 移除冗余判断:即使没有匹配到标签,
split返回的原字符串列表经过循环处理后,也会统一转小写,和直接调用i18n_lower(value)效果一致,简化代码逻辑。
内容的提问来源于stack exchange,提问作者TToprak1
相关产品推荐
相关产品推荐

