我使用的是第三方文件重命名软件,该软件是用Delphi编写的,并且支持pascal脚本:http://www.den4b.com/?x=products&product=renamer
应用程序允许使用正则表达式重命名文件。这意味着如果我只需要使用一个RegEx就无法完成文件名所需,那么我可以同时使用各种表达式或pascal脚本代码来容纳文件名,直到我可以正确格式化文件名以满足此需求问题或其他任何事情......
我需要格式化下面的歌曲文件名,在这些文件名中使用" ...特色艺术家" part位于字符串的右侧,我需要将其匹配并将其放置在字符串的左侧部分。
为了使这个简单易懂,我们可以想象 tokenize 这样的文件名:
[0]ARTIST [1]DASH [2]TRACK [3]FEAT_ARTIST [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
然后我需要对RegEx做什么,格式化文件名以按此顺序定位标记:
[0]ARTIST [3]FEAT_ARTIST [1]DASH [2]TRACK [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
我实际上是使用此RegEx执行此操作:
\ A([^ - ]的?)\ S - (?)\ S * \ S ([([])((英尺[?。 \ S] |技艺??[\ S] |。设有[\ S])[^(){} []] *)([)]])(+)\ž
替换为:
$ 1 $ 4 - $ 2 $ 7
问题从这里开始,因为[0]ARTIST
和[2]TRACK
令牌可能包含破折号,例如此文件名:
然后,如果我错了,请纠正我,但我认为以任何方式解决这个问题都是不可能的,因为机器无法预测何时将一个令牌与另一个令牌分开,这是什么名字或者什么不是,因为我不知道包含文件名的破折号码。
出于这个原因,而不是寻找可能导致不良的ingenuos完美 文件名因为内部破折号的数量,我更愿意寻找一个 文件名排除解决方案,通过限制表达式的破折号 应该在文件名中匹配。
以我上面展示的RegEx为例来扩展/改进它,如何排除包含带有短划线的[0]ARTIST
或[2]TRACK
令牌的文件名?
...或者换句话说,当文件名包含多于1个破折号 " ...特色时,我怎么能告诉我的RegEx避免修改文件名艺术家"部分? (不是之后)
基本上,正则表达式应确定在[1]DASH
之前是否多次找到[3]FEAT_ARTIST
,如果是,则排除该文件名(不要修改它)
我知道如何限制正则表达式组的出现,或多或少像([\-]){1}
这样只匹配1个短划线,但我不确定如何在表达式I&#39中实现它;使用。
只是一些随机的例子......
仅在[3]FEAT_ARTIST
之前的一个短划线,以便我们知道何时将[0]ARTIST
与[2]TRACK
代币分开。
仅在[3]FEAT_ARTIST
之前的一个短划线,以便我们知道何时将[0]ARTIST
与[2]TRACK
代币分开。使用[4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
。
仅在[3]FEAT_ARTIST
之前的一个短划线,以便我们知道何时将[0]ARTIST
与[2]TRACK
代币分开。 [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
也包含破折号。
仅在[0]ARTIST
和[2]TRACK
令牌之间使用一个短划线,但文件名没有[3]FEAT_ARTIST
,因此我们无法触摸它。
仅在[0]ARTIST
和[2]TRACK
令牌之间使用一个短划线,但[3]FEAT_ARTIST
位于[1]DASH
之前,因此我们无法触及它。
[0]ARTIST
有短划线,因此我们无法知道何时将[0]ARTIST
和[2]TRACK
令牌分开,因此正则表达式应将其排除在外,以免修改此文件名
[2]TRACK
有短划线,因此我们无法知道何时将[0]ARTIST
和[2]TRACK
令牌分开,因此正则表达式应将其排除在外,以免修改此文件名
[0]ARTIST
和[2]TRACK
令牌有破折号,因此我们无法知道何时将它们分开,因此正则表达式应排除这一点以免修改此文件名。
[0]ARTIST
和[2]TRACK
令牌有破折号,而[3]FEAT_ARTIST
也不存在,此处无处可做。
我希望这有助于理解我的需要。
答案 0 :(得分:1)
我认为你唯一需要意识到/改变的是“分隔符连字符”和“嵌入连字符”之间存在明显区别。也就是说,没有嵌入的连字符在两个边上都有空格(我希望;你需要验证它)。您需要做的就是将正则表达式的开头从\A([^-]?)\s-\s*
更改为\A(.?)\s-\s+
...
答案 1 :(得分:1)
我将所有文件名放入文本编辑器UltraEdit 22.10版:
Carbin & Sirmark - Sorry Feat. Sevener
Kristjan Cash Cash - Take Me Home Feat. Bebe Rexha (Revoke Remix)
Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole
Flight Facilities - Heart Attack Feat. Owl Eyes (Snakehips Remix)
Flight Facilities - Heart Attack Feat. Owl Eyes [Snake--hips Remix]
Fedde Le Grand - Cinematic
Fedde Le Grand Feat. Denny White - Cinematic
Artist-Name - Track Name feat someone
Artist Name - Track-Name feat someone
Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole
Dj E-nergy C-21 - My Super-hero track!
使用Perl正则表达式搜索字符串
^(.+) - (.+?) ((?:featuring|feat\.?|ft\.?) +(?:[^\r\n (\[{]| (?![(\[{]))+)
和替换字符串
$1 $3 - $2
这些文件名使用不区分大小写的全部替换修改为
Carbin & Sirmark Feat. Sevener - Sorry
Kristjan Cash Cash Feat. Bebe Rexha - Take Me Home (Revoke Remix)
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
Flight Facilities Feat. Owl Eyes - Heart Attack (Snakehips Remix)
Flight Facilities Feat. Owl Eyes - Heart Attack [Snake--hips Remix]
Fedde Le Grand - Cinematic
Fedde Le Grand Feat. Denny White - Cinematic
Artist-Name feat someone - Track Name
Artist Name feat someone - Track-Name
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
Dj E-nergy C-21 - My Super-hero track!
看起来像你想要的。 UltraEdit使用Boost Perl正则表达式库。
如果文件重命名工具也支持负向前瞻和贪婪匹配行为,则表达式可能对此任务有用:
\A(.+) - (.+?) ((?:featuring|feat\.?|ft\.?) +(?:[^ (\[{]| (?![(\[{]))+)
,替换字符串也是:
$1 $3 - $2
搜索字符串的说明:
^
...开始行
\A
...缓冲区的开始
(.+) -
...一个贪婪表达式,它匹配任何字符1次或多次(换行符除外)直到最后出现空格 划线 空格在不包括 -
的标记组中,其结果仍然是整个表达式的正匹配。
(.+?)
...一个非贪婪表达式也位于匹配任何字符(换行符除外)的捕获组中,一次或多次直到下一次出现空格并且......
(?:featuring|feat\.?|ft\.?) +
...字featuring
或缩写feat
,带或不带点或缩写ft
,带或不带点和1个或多个空格。
(
...从第三个捕获组开始。
(?:[^\r\n (\[{]| (?![(\[{]))+
...与
或
一次或多次。换句话说,最后一个表达式匹配文件名末尾的所有内容或(
或[
或{
,不包括留给这些字符的空格以避免获取 space FEAT_ARTIST之后的 space dash 。
)
...终于结束了第三个捕获组。
编辑1:同时工作(在UltraEdit中)是搜索字符串:
^(.+) - (.+?) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
除了featuring.
之外,它会使表达更容易一些。
编辑2:同样工作(在UltraEdit中)是搜索字符串:
^((?:.(?! - ))+.) - ((?:.(?! - ))+) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
忽略包含两个空格 破折号 空格的所有行左侧FEAT_ARTIST
。
如果当前字符后面的字符串不是 space dash space ,则此表达式逐字符匹配使用否定前瞻。这是第一个捕获组,允许选择第一个空间 破折号 空间左边的最后一个字符的字符串,但对于第二个捕获组,应该不再是 space dash space ,因为这肯定会导致整个表达式产生负面结果。
答案 2 :(得分:1)
尝试:
^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$
并使用替换为:$1 Feat.$5 - $2$6
我尝试使用ReNamer和Regex101,如果艺术家名称中有-
( +
-
+ ),它也会有效,例如{{1但是,如果标题部分中有这样的片段,它将失败。
artist - name
部分在序列空间 - 破折号空间之前使用贪心量词^(.+)\s+-\s+
,它被视为艺术家姓名和曲目标题之间的分隔符。所以它会尽可能多地匹配,直到最后一次出现.+
,因此,它会“忽略”带有艺术家名字空格的破折号,但是如果这样的元素出现则会无效匹配在曲目标题。所以:
-
- 它将匹配并且
修改得当,Artist - name - track title feat. someone
- 它会失败,就像文字一样
将在最后一个破折号上拆分。而不是Artist name - track - title feat. someone
我使用匹配相似的(ft[.\s]|feat[.\s]|featuring[.\s])
,但应该更快地工作(它应该稍微限制回溯)。
在我的演示中,有一个[fF](t|eat(uring)?)?\.?
而不是+
(如上所述),因为它会在演示中匹配多行,并显示无效结果,但在oneline情况下,就像你的问题一样,它应该工作正常。
答案 3 :(得分:0)
在@ m.cekiera 的正则表达式的帮助下,我通过使用pascal脚本解决了这个问题,该脚本在文件名中找到多个破折号时阻止了任何替换:
// Formats an audio filename that has the "...featuring artist" part at the end of filename.
//------------------------------------------------------------------------------------------
// Pseudo-Example:
//
// From: [0]ARTIST_NAME [1]DASH [2]TRACK_TITLE [3]FEAT_ARTIST [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
// To: [0]ARTIST_NAME [3]FEAT_ARTIST [1]DASH [2]TRACK_TITLE [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
// Real-Example:
//
// From: Carbin & Sirmark - Sorry Feat. Sevener.mp3
// To: Carbin & Sirmark Feat. Sevener - Sorry.mp3
// Known limitations:
//
// • If [0]ARTIST_NAME or [2]TRACK_TITLE parts contains any " - " the script will not work properlly.
// By default the script prevents any replacement on that kind of filenames, so don't worry.
var
rgxPattern: string;
rgxReplace: string;
dashCount: integer;
baseName: string;
extension: WideString;
begin
baseName := WideExtractBaseName(FileName)
extension := WideExtractFileExt(FileName);
// The regular expression that matches the filename parts.
// http://stackoverflow.com/questions/32807698/regex-pattern-to-limit-dashes-in-these-circumstances
rgxPattern := '^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$'
rgxReplace := '$1 Feat.$5 - $2$6'
// The amount of " - " that contains the filename.
dashCount := high(MatchesRegEx(baseName, '\s-\s' , false));
// If only one " - " is found then...
If (dashCount = 0) Then
begin // Do the replacement.
baseName := ReplaceRegEx(baseName, rgxPattern, rgxReplace, false, true)
FileName := baseName + extension;
end;
end.