如何用正则提取Usenet主题中含嵌套[]的类文件名
Usenet主题中含嵌套方括号的文件名提取方案
问题背景
原正则表达式r"([\w\-+()'\s.,]{5,}\.[A-Za-z0-9]{2,4})[^A-Za-z0-9]"能较好提取Usenet主题中的类文件名,但遇到文件名含嵌套[]且自身被[]包裹的场景时失效。例如输入:
[Text]-[Text]-[Filename[Uploader].txt]-[1/23] - "" yEnc 1234567890 (1/23456)
需要提取Filename[Uploader].txt,直接将[]加入字符组会误匹配外层括号,需调整正则逻辑。
补充测试用例(输入→预期输出):
test_cases = [ ('Subject-KrzpfTest [02/30] - ""KrzpfTest.part.nzb"" yEnc', "KrzpfTest.part.nzb"), ('[PRiVATE]-[WtFnZb]-[Supertje-_S03E11-12_-blabla_+_blabla_WEBDL-480p.mkv]-[4/12] - "" yEnc 9786 (1/1366)', "Supertje-_S03E11-12_-blabla_+_blabla_WEBDL-480p.mkv"), ('[N3wZ] MAlXD245333\\::[PRiVATE]-[WtFnZb]-[Show.S04E04.720p.AMZN.WEBRip.x264-GalaxyTV.mkv]-[1/2] - "" yEnc 293197257 (1/573)', "Show.S04E04.720p.AMZN.WEBRip.x264-GalaxyTV.mkv"), ("Singer - A Album (2005) - [04/25] - 02 Sweetest Somebody (I Know).flac", "Singer - A Album (2005) - [04/25] - 02 Sweetest Somebody (I Know).flac"), ('[PRiVATE]-[WtFnZb]-[00000.clpi]-[1/46] - "" yEnc 788 (1/1)', "00000.clpi"), ("[PRiVATE]-[WtFnZb]-[/More.Bla.S02E01.1080p.WEB.h264-EDITH[eztv.re].mkv] yEnc 2990558544 (1/4173)", "More.Bla.S02E01.1080p.WEB.h264-EDITH[eztv.re].mkv") ]
解决方案
针对嵌套方括号场景,使用支持嵌套匹配的正则表达式,同时排除分卷标记(如[1/23])的干扰:
适配Python 3.10+(支持无限嵌套)
import re # 支持任意深度嵌套[]的正则 pattern = re.compile(r''' (?:\[)? # 匹配可选的外层左括号 ( (?: [^\[\]]+ # 匹配非括号字符 | \[ (?R) \] # 递归匹配嵌套的[]结构 )+? # 非贪婪匹配,避免过度延伸 \.[A-Za-z0-9]{2,4} # 匹配文件名扩展名(2-4位) ) (?:\])? # 匹配可选的外层右括号 (?! \d+/\d+ ) # 排除后面跟着分卷标记(如1/23)的情况 ''', re.VERBOSE)
适配低版本Python(支持两层嵌套)
如果使用Python 3.10以下版本,可使用非递归模式适配常见的两层嵌套场景:
pattern = re.compile(r''' (?:\[)? ( (?: [^\[\]]+ | \[ (?: [^\[\]]+ | \[ [^\[\]]* \] )* \] )+? \.[A-Za-z0-9]{2,4} ) (?:\])? (?! \d+/\d+ ) ''', re.VERBOSE)
测试验证
将测试用例代入验证,代码如下:
for input_str, expected in test_cases: match = pattern.search(input_str) if match: # 处理部分文件名开头的多余斜杠 result = match.group(1).lstrip('/') assert result == expected, f"匹配失败:提取结果{result}≠预期{expected}" print("所有测试用例验证通过")
逻辑说明
- 嵌套括号处理:通过递归(
(?R))或分层匹配,识别文件名内部的嵌套[],避免误匹配外层括号; - 扩展名约束:保留原正则对扩展名的匹配规则,确保提取内容为类文件名;
- 分卷标记排除:通过负向预测
(?! \d+/\d+ ),避免将[1/23]这类分卷标记误识别为文件名; - 兼容性:提供低版本Python的替代方案,覆盖常见嵌套场景。
内容的提问来源于stack exchange,提问作者Safihre
相关产品推荐
相关产品推荐

