我正在尝试构建灵活的正则表达式来挑选媒体文件的艺术家姓名和歌曲名称。我希望它具有灵活性并支持以下所有内容:
01示例艺术家 - 示例Song.mp3
01示例Song.mp3 (在这个例子中,没有艺术家,所以组应该为空)
示例艺术家 - 示例Song.mp3
示例Song.mp3 (再一次,没有艺术家)
我已经提出以下内容(在.NET语法中,特别是对于命名捕获组):
\d{0,2}\s*(?<artist>[^-]*)?[\s-]*(?<songname>.*)(\.mp3|\.m4a)
这很有效,但输入失败了: 01示例Song.mp3
它吞噬了歌曲的名字作为艺术家,我相信因为贪婪的匹配。因此,我尝试修改表达式,以便艺术家部分将是懒惰匹配:
\d{0,2}\s*(?<artist>[^-]*)*?[\s-]*(?<songname>.*)(\.mp3|\.m4a)
改变是:
(?<artist>[^-]*)?
成了
(?<artist>[^-]*)*?
这确实解决了上述问题。但现在,它输入失败了:
01示例艺术家 - 示例Song.mp3
现在,它太懒了,因为它捕获了&#34;示例艺术家 - 示例歌曲&#34;作为歌曲名称,并没有为艺术家的名字捕捉任何内容。
有没有人对此提出建议?
答案 0 :(得分:3)
只有贪婪才能实现此任务,您需要使用群组更具描述性(可选或不可选)。一个例子:
(?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
仅用于测试目的,您可以在一次应用模式一个文件名时将其删除)