0

所以我需要一个正则表达式忍者来帮助我解决这个问题,因为我对正则表达式知之甚少。我希望能够根据掩码从文件名中检索有关歌曲的信息。这是一个例子:

G:\Music\G\Green Day\(2001) International Superhits!\02. Green Day - Poprocks & Coke.mp3

所以面具将是:

$artist$\$album$\$track$. $artist$ - $title$.mp3

似乎正则表达式非常适合这个,因为它只处理字符串。有人有解决方案吗?

谢谢,兰迪

PS我知道如何通过代码来做到这一点......希望用正则表达式完成它。

4

2 回答 2

3

是的,这可以通过正则表达式实现。如果您自己编写掩码,则应立即将其编写为正则表达式。如果没有,您将不得不将其转换为一个,但这应该不会太难,一旦您看到模式的样子。

主要问题是,这些变量可以包含什么。为简单起见,对于它们中的每一个,我假设它们可以包含除反斜杠之外的任何字符。这样的字符由 匹配[^\\]。这是一个否定字符类,它匹配除内部字符之外的所有字符(第一个反斜杠用于转义第二个反斜杠)。您可以重复此操作+(至少需要一个字符)。对于赛道,我会例外,只允许数字。

所以这会让你的模式像

[^\\]+\\[^\\]+\\\d+[.]\s*[^\\]+\s*-\s*[^\\]+[.]mp3$

是将$模式锚定到字符串的末尾。

请注意,我将句点放在字符类中。否则,它们将匹配除换行符之外的任何字符 - 您也可以转义句点,但我更喜欢字符类以提高可读性。对于空格,我使用\s*了 ,它匹配任意数量(和种类)的空格,包括根本没有空格。

现在的问题是如何将其纳入您的变量中。您可以通过将所需部分括在括号中来捕获部分匹配项。但更有用的是您可以使用(?<name>pattern)语法为这些捕获命名。像这样:

(?<artist>[^\\]+)\\(?<album>[^\\]+)\\(?<track>\d+)[.]\s*(?<artist>[^\\]+)\s*-\s*(?<title>[^\\]+)[.]mp3$

最后,您如何访问结果?

Dim text As String = "G:\Music\G\Green Day\(2001) International Superhits!\02. Green Day - Poprocks & Coke.mp3" 
Dim pattern As String = "(?<artist>[^\\]+)\\(?<album>[^\\]+)\\(?<track>\d+)[.]\s*(?<artist>[^\\]+)\s*-\s*(?<title>[^\\]+)[.]mp3$" 

' Instantiate the regular expression object. 
Dim r As Regex = new Regex(pattern)

' Match the regular expression pattern against a text string. 
Dim m As Match = r.Match(text)
If m.Success Then
    ' get results from m.Groups["artist"].Value etc.

还有一个微妙之处。您的面具/图案包含艺术家两次。.NET 没有重复组名的问题。问题是您要如何处理它们是两个不同名称的情况。我上面写的代码只会给你两个版本中的后者。实际上,您可以在m.Groups["artist"].Captures[0].Value和中访问它们m.Groups["artist"].Captures[1].Value

如果你想断言它们是相同的——如果它们不同则只是不匹配——你可以使用反向引用来代替第二组。反向引用与它引用的组捕获的内容完全匹配:

(?<artist>[^\\]+)\\(?<album>[^\\]+)\\(?<track>\d+)[.]\s*\k<artist>\s*-\s*(?<title>[^\\]+)[.]mp3$

\k<artist>确保您与artist在路径中找到的完全匹配。

像皮特一样,我只能推荐这个教程。要进一步了解我在上面使用的构造,您可能需要特别查看这些小节:

学习正则表达式绝对值得你花时间。您不仅肯定会遇到另一个可以轻松解决的问题 - 当涉及到您选择的文本编辑器中的简单搜索和替换任务时,它还会大大提高您的工作效率。

编辑:最后一点。如果您要经常使用这种模式,并且性能很重要,那么您可能会从使用 .NET 的从右到左模式中获益良多。你可以像这样激活它

...
Dim r As Regex = new Regex(pattern, RegexOptions.RightToLeft)
...

但是,如果您想知道为什么会有所不同,我建议您阅读链接的教程。;)

于 2013-06-13T00:42:40.590 回答
0

我相信这对你有用:

^(?<drive>[^:]+):\\(?<folder>Music)\\(?<subfolder>[^\\]+)\\(?<group>[^(]+)\\\((?<year>[^)]+)\)\s+(?<album>[^\\]+)\\(?<track>[^.]+)\.\s*(?<artist>.+?) - (?<title>[^.]+)\.mp3$

分解它以获得解释:

^                       'start of string
(?<drive>[^:]+)         'named capture group "drive", captures any character except :
:\\                     'finds : followed by "\" ("\" has to be escaped to be a literal "\", so \\ is needed here)
(?<folder>Music)        'named capture group "folder", captures Music
\\                      'finds "\"
(?<subfolder>[^\\]+)    'named capture group "subfolder", captures any character except "\"
\\                      'finds "\"
(?<group>[^(]+)         'named capture group "group", captures any character except "\"
\\                      'finds "\"
\(                      'finds ( (parentheses must be escaped to be a literal "(" or literal ")", so \( is needed here)
(?<year>[^)]+)\)        'named capture group "year", captures any character except "("
\s+                     'finds whitespace
(?<album>[^\\]+)        'named capture group "album", captures any character except "("
\\                      'finds "\"
(?<track>[^.]+)         'named capture group "track", captures any character except "."
\.                      'finds "." (outside of a character class, "." must be escaped, so \. is needed here)
\s*                     'finds whitespace
(?<artist>.+?)          'named capture group "artist", captures any character (lazily)
 -                      'finds " - "
(?<title>[^.]+)         'named capture group "title", captures any character (greedily)
\.mp3                   'finds ".mp3"
$                       'end of string

这是一个非常好的正则表达式在线入门:http ://www.regular-expressions.info/

我可能会补充一点,对于离线资源,您当然可以比 O'Reilly Media 的 Jeffrey EF Friedl 的“掌握正则表达式”做得更糟。我有第 2 版,它帮助我理解 Regex,以至于我很少需要询问有关 Regex 的问题。

我还购买了(并且喜欢)Jan Goyvaerts 的 RegexBuddy。这是一个用于编写和理解正则表达式的非凡软件。

于 2013-06-13T00:42:29.557 回答