【问题标题】:Regex to pick out artist name and song title, issue with lazy matching正则表达式选择艺术家姓名和歌曲名称,延迟匹配问题
【发布时间】:2015-11-24 03:22:45
【问题描述】:

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

01 Example Artist - Example Song.mp3

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

示例艺术家 - 示例 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”捕获为歌曲名,而没有捕获任何艺术家名。

有人对此有什么建议吗?

【问题讨论】:

    标签: .net regex regex-greedy


    【解决方案1】:

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

    (?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 仅用于测试目的,您可以在一次应用一个文件名的模式时将其删除)

    【讨论】:

    • PS:我也没有意识到您可以嵌套捕获组。它们(与 cmets 一起)使阅读正则表达式更加清晰。再次感谢。
    • 问题:(参考上面的第一个正则表达式)我看到对于艺术家,你做了一个惰性匹配 (?.+?),最后带有问号。但是对于标题,您省略了我认为意味着贪婪匹配的问号。这确实有效,但为什么呢?为什么要填充 ext 组?为什么标题不吞下“.mp3”而不是让ext拥有它?我想更好地理解这一点。
    • 我想我已经回答了我自己的问题:“ext”部分不是可选的,所以为了满足正则表达式,它会被优先考虑。
    • @BenjiFB:这不是因为 ext 部分不是可选的。原因是当您对“艺术家”组使用贪婪量词.+ 时,正则表达式引擎只需要 4 个回溯步骤(扩展名的 4 个字符,因为.+ 一直到最后),但是如果我改为使用非贪婪量词.+?,对于每个字符,正则表达式引擎必须测试以下子模式\s*-\s*)?(?&lt;title&gt; .+)(?&lt;ext&gt; \.m(?:p3|4a)) 是否失败,直到该子模式成功。如果您假设大多数时候艺术家姓名的长度大于 4 个字符,那么贪婪量词是更好的选择。
    猜你喜欢
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多