我正在尝试构建一个灵活的正则表达式来挑选媒体文件的艺术家姓名和歌曲标题。我希望它能够灵活并支持以下所有内容:
01 示例艺术家 - 示例歌曲.mp3
01 示例歌曲.mp3 (在此示例中,没有艺术家,因此该组应该为空)
示例艺术家 - 示例歌曲.mp3
示例歌曲.mp3 (再次强调,没有艺术家)
我提出了以下内容(使用 .NET 语法,特别是对于命名捕获组):
\d{0,2}\s*(?<artist>[^-]*)?[\s-]*(?<songname>.*)(\.mp3|\.m4a)
这运行良好,但对于此输入失败: 01 示例歌曲.mp3
它吞掉了艺术家的歌曲名称,我相信是因为贪婪匹配。因此,我尝试修改表达式,使艺术家部分延迟匹配:
\d{0,2}\s*(?<artist>[^-]*)*?[\s-]*(?<songname>.*)(\.mp3|\.m4a)
变化是:
(?<artist>[^-]*)?
成为了
(?<artist>[^-]*)*?
这确实解决了上述问题。但现在,这个输入失败了:
01 示例艺术家 - 示例歌曲.mp3
现在,它太懒了,它捕获“示例艺术家 - 示例歌曲”作为歌曲名,但没有捕获任何艺术家名称。
有人对此有建议吗?
最佳答案
仅靠贪婪是无法完成此任务的,您需要使用组(可选或不可选)来更具描述性。一个例子:
(?x) # switch on comment mode
^ # start of the string
(?: (?<track>\d{1,3}) \s*[\s-]\s* )? # the track is optional ( including separators)
(?: (?<artist>.+?) \s*-\s* )? # the same with the artist name
(?<title> .+ )
(?<ext> \.m(?:p3|4a) )
顺便说一句,音频文件名可能非常奇怪,即使使用世界上最好的模式,我怀疑您是否可以处理所有情况。
如果将 .+
替换为更明确的内容,您可以更加灵活和高效:
^(?x)
(?: (?<track>\d{1,3}) \s*[\s-]\s* )?
(?: (?<artist> \S+ (?>[ .-][^\s.-]*)*? ) \s*-\s*)?
(?<title> [^.\n]+ (?>\.[^.\n]*)*? )
(?<ext> \.m(?:p3|4a) )
(\n
仅用于测试目的,您可以在一次应用模式一个文件名时将其删除)
关于.net - 正则表达式挑选艺术家姓名和歌曲标题,存在惰性匹配问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32288423/