3

所以我正在编写一个程序来根据找到的文件打印音乐书籍。我已经可以选择读取完成的标签,但解析文件名要快得多,所以我决定让它成为一个选项。用户将提供类似于以下内容的掩码:

    (%year%) %album%\%track%. %artist% - %title%

所以我需要用代码创建正则表达式。我几乎完成了,但在空间方面遇到了问题。我需要能够匹配掩码中提供的确切空格数。这是我到目前为止所拥有的:

    ^(?<track>[^.]+)\.[ ](?![ ])(?<artist>.+?)[ ](?![ ])-[ ](?![ ])(?<title>[^.]+)\.mp3$

前瞻工作一切正常,除了破折号之前的那个。不知道为什么。它将允许多个空格(但不允许 0 个空格)。所以我需要的是我可以为我找到的每个空间“插入”到掩码中的东西,它只会匹配那个空间。

4

2 回答 2

1

问题

问题在于您的名为 captures 的正则表达式,它正在收集所有非.字符。字符类[^.]也匹配一个空格。所以像这样的表达式\s{1}([^.]+)\s{2}\.将允许:

 SomeTitle    .mp3
^^^^^^^^^^^^  
   SomeTitle  .mp3
  ^^^^^^^^^^  

捕获组将获得带下划线的部分,包括带下划线的前导或尾随空格。这实质上允许在源字符串中存在更多的空格,而不是期望的。要解决此问题,您需要(?!\s)在每个所需的空格匹配后使用前瞻,以确保字符类捕获的下一个字符不会是像 `\s{1}(?!\s)([^ .]+)\s{2}(?!\s)。

解决方案

此正则表达式将从以下格式的字符串中捕获曲目、艺术家和标题:(%year%) %album%\%track%. %artist% - %title%. 要确保下一个字符不是空格,请使用(?!\s). 这是插入一个结尾

^\((?<year>[^)]*)\)\s{1}(?!\s)(?<album>[^\\]*)\\(?<track>[^.]*)\.\s{1}(?!\s)(?<artist>(?:(?!\s{1}-\s{1}).)+?[^\s])\s{1}-\s{1}(?!\s)(?<title>[^.]*?[^.\s])\.(?<ZeroLengthSpaceAfterDot>(?!\s))mp3

在此处输入图像描述

在图像中,第 1 组 = 年份,第 2 组 = 专辑,第 3 组 = 曲目,第 4 组 = 艺术家,第 5 组 = 标题,第 6 组是零空格的示例

VB.NET 代码示例:

输入文本

(%year%) %album%\%track%. %artist% - %title%.mp3
(1971) Punk Kittens\1of3. Kittens - I Like cats.mp3
(1969) Muppet Show\2of3. Pigs - Pigs In Space. mp3
(1991) Foo Shivle\3of3. Snoop Dog - Just another brick in the pound.mp3
(2009) Space Race\3of3. Sir Space Alot -  Too many Spaces.mp3

代码示例

Imports System.Text.RegularExpressions
Module Module1
  Sub Main()
    Dim sourcestring as String = "replace with your source string"
    Dim re As Regex = New Regex("^\((?<year>[^)]*)\)\s{1}(?!\s)(?<album>[^\\]*)\\(?<track>[^.]*)\.\s{1}(?!\s)(?<artist>(?:(?!\s{1}-\s{1}).)+?[^\s])\s{1}-\s{1}(?!\s)(?<title>[^.]*?[^.\s])\.(?<ZeroLengthSpaceAfterDot>(?!\s))mp3",RegexOptions.IgnoreCase OR RegexOptions.Multiline OR RegexOptions.Singleline)
    Dim mc as MatchCollection = re.Matches(sourcestring)
    Dim mIdx as Integer = 0
    For each m as Match in mc
      For groupIdx As Integer = 0 To m.Groups.Count - 1
        Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)
      Next
      mIdx=mIdx+1
    Next
  End Sub
End Module

火柴

$matches Array:
(
[0] => Array
    (
        [0] => (%year%) %album%\%track%. %artist% - %title%.mp3
        [1] => (1971) Punk Kittens\1of3. Kittens - I Like cats.mp3
        [2] => (1991) Foo Shivle\3of3. Snoop Dog - Just another brick in the pound.mp3
    )

[year] => Array
    (
        [0] => %year%
        [1] => 1971
        [2] => 1991
    )


[album] => Array
    (
        [0] => %album%
        [1] => Punk Kittens
        [2] => Foo Shivle
    )


[track] => Array
    (
        [0] => %track%
        [1] => 1of3
        [2] => 3of3
    )


[artist] => Array
    (
        [0] => %artist%
        [1] => Kittens
        [2] => Snoop Dog
    )

[title] => Array
    (
        [0] => %title%
        [1] => I Like cats
        [2] => Just another brick in the pound
    )


[ZeroLengthSpaceAfterDot] => Array
    (
        [0] => 
        [1] => 
        [2] => 
    )


)

空间选项

  • \s\s{1}匹配一个空格
  • \s(?!\s)匹配一个空格并确保空格后面的字符不是空格。
  • \s*匹配零个或多个空格
  • \s{2,}匹配两个或多个空格
  • (?!\s)确保下一个字符不是空格
  • (?!\s{6})确保接下来的六个字符不是全是空格
于 2013-06-16T19:50:22.277 回答
0

尝试这个:

^(?<track>[^.]+)\. (?! )(?<artist>.+?[^ ]) (?! )- (?! )(?<title>[^.]+)\.mp3$
                  ^                       ^      ^

指定上面三个空格保持器中任何一个的长度^以匹配掩码。

我使用 RegexBuddy 测试了上述正则表达式模式。结果如下图所示:-

在此处输入图像描述

于 2013-06-16T18:31:59.177 回答