正则表达式来挑选艺术家姓名和歌曲标题,延迟匹配问题

Regex to pick out artist name and song title, issue with lazy matching

我正在尝试构建一个灵活的正则表达式来挑选媒体文件的艺术家姓名和歌曲名称。我希望它灵活并支持以下所有内容:

01 Example Artist - Example Song.mp3

01例歌.mp3 (在此示例中,没有艺术家,因此该组应该为空)

Example Artist - Example Song.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 Example Artist - Example Song.mp3

现在,它太懒了,因为它捕获 "Example Artist - Example Song" 作为歌曲名称,而没有捕获任何艺术家名称。

有人对此有什么建议吗?

你不能只靠贪婪来完成这个任务,你需要使用组(可选或不可选)来更具描述性。一个例子:

(?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) )

demo

顺便说一句,音频文件名可能很奇怪,即使是世界上最好的模式,我怀疑你能处理所有情况。

如果将 .+ 替换为更明确的内容,您可以更加灵活和高效:

^(?x)
(?: (?<track>\d{1,3}) \s*[\s-]\s* )?
(?: (?<artist> \S+ (?>[ .-][^\s.-]*)*? ) \s*-\s*)?
(?<title> [^.\n]+ (?>\.[^.\n]*)*? )
(?<ext> \.m(?:p3|4a) )

\n 仅用于测试目的,您可以在一次应用模式一个文件名时删除它们)