所以我需要一个正则表达式的忍者来帮助我,因为我对Regex知之甚少。我希望能够根据掩码从文件名中检索有关歌曲的信息。这是一个例子:
G:\Music\G\Green Day\(2001) International Superhits!\02. Green Day - Poprocks & Coke.mp3
所以面具将是:
$artist$\$album$\$track$. $artist$ - $title$.mp3
似乎Regex对此非常完美,因为它只是处理字符串。有人有解决方案吗?
谢谢, 好色
P.S。我知道如何通过代码来实现...希望用Regex完成它。
答案 0 :(得分: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
。
像皮特一样,我只能推荐this tutorial。为了进一步了解我上面使用的构造,您可能希望特别查看这些小节:
学习正则表达式绝对值得您花时间。您不仅会遇到另一个可以轻松解决的问题 - 在您选择的文本编辑器中进行简单的搜索和替换任务时,它还可以提高您的工作效率。
编辑:最后一点说明。如果您要使用这种模式,并且性能至关重要,那么使用.NET的从右到左模式可能会获得很多收益。您可以像
一样激活它...
Dim r As Regex = new Regex(pattern, RegexOptions.RightToLeft)
...
但是如果你想知道为什么会产生影响,我建议你阅读链接教程。 ;)
答案 1 :(得分: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 E.F.Friedl的“掌握正则表达式”更糟糕。我有第2版,它帮助我理解正则表达式,我很少需要提出有关正则表达式的问题。
我还购买了(并且喜欢)Jan Goyvaerts的RegexBuddy。这是用于撰写和理解Regex的非凡软件。