在这些情况下限制破折号的 RegEx 模式
RegEx pattern to limit dashes in these circumstances
场景
我正在使用一个用 Delphi 编写并支持 pascal 脚本的第三方文件重命名软件:http://www.den4b.com/?x=products&product=renamer
该应用程序允许使用正则表达式来重命名文件。这意味着如果我需要用一个文件名做的事情不能仅使用一个 RegEx 来完成,那么我可以同时使用各种表达式或 pascal 脚本代码来容纳文件名,直到我可以根据需要正确格式化文件名问题或其他...
问题
我需要像下面这样格式化歌曲文件名,在这些文件名中,“...featuring artist”部分位于字符串的右侧,我需要匹配它并将其放在字符串的左侧。
- Carbin 和 Sirmark - 对不起壮举。七人
- Kristjan Cash Cash - 带我回家壮举。 Bebe Rexha(撤销混音)
为了便于理解,我们可以想象 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:()[]{}
我实际上使用这个正则表达式来做到这一点:
\A([^-]?)\s-\s*(.?)\s([([])?((ft[.\s]|feat[.\s]|featuring[.\s])[^(){}[]]*)([)]])?(.+)?\Z
替换为:
-
问题从这里开始,因为 [0]ARTIST
和 [2]TRACK
标记可能包含破折号,例如这个文件名:
- Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼
然后,如果我错了,请纠正我,但我认为它不可能以任何方式解决这个问题,因为机器无法预测何时将一个标记与另一个标记分开,什么是名称或什么不是,因为我不知道包含文件名的破折号的数量。
For that reason, instead of looking for ingenuos perfection that could cause bad
filenames because the amount of dashes inside, I prefer to look for a
filename exclusion solution, by limiting the dashes that the expression
should match in the filename.
问题
以我上面显示的 RegEx 为例 extend/improve 它,我如何排除包含 [0]ARTIST
或带破折号的 [2]TRACK
标记的文件名?
...或者换句话说,当文件名包含超过 1 个破折号 before " 时,我如何告诉我的 RegEx 避免修改文件名...特色艺术家”部分? (不在之后)
基本上,Regex 应该确定 [1]DASH
是否在 [3]FEAT_ARTIST
之前被多次找到,如果是,则排除该文件名(不要修改它)
我知道如何限制 Regex 组的出现次数或多或少像这样 ([\-]){1}
以仅匹配 1 个破折号出现,但我不确定如何在表达式中实现它使用。
预期结果
只是一些随机的例子...
只有在 [3]FEAT_ARTIST
之前有一个破折号,这样我们就可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。
- 发件人:'Carbin & Sirmark - 对不起壮举。七人'
- 收件人:'Carbin & Sirmark Feat。 Sevener - 抱歉'
仅在 [3]FEAT_ARTIST
之前有一个破折号,因此我们可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。 [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
.
- 来自:'飞行设施 - 心脏病专长。 Owl 眼睛(蛇臀混音)'
- 收件人:'飞行设施专长。 Owl 眼睛 - 心脏病发作 (Snakehips Remix)'
仅在 [3]FEAT_ARTIST
之前有一个破折号,因此我们可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。 [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
也包含破折号。
- 来自:'飞行设施 - 心脏病专长。 Owl眼睛[蛇--臀Remix]'
- 收件人:'飞行设施专长。 Owl眼睛-心脏病发作[蛇--臀Remix]'
仅在 [0]ARTIST
和 [2]TRACK
标记之间有一个破折号,但文件名没有 [3]FEAT_ARTIST
所以我们不碰它。
- 来自:'Fedde Le Grand - 电影'
- 收件人:'Fedde Le Grand - 电影'
仅在 [0]ARTIST
和 [2]TRACK
标记之间有一个破折号,但是 [3]FEAT_ARTIST
在 [1]DASH
之前,所以我们不碰它。
- 发件人:'Fedde Le Grand Feat。丹尼怀特 - 电影'
- 致:'Fedde Le Grand Feat。丹尼怀特 - 电影'
[0]ARTIST
有破折号,所以我们不知道什么时候分开 [0]ARTIST
和 [2]TRACK
标记,所以正则表达式应该排除这个不要修改这个文件名。
- 发件人:'艺术家姓名 - 曲目名称专长'
- 收件人:'艺术家姓名 - 曲目名称专长'
[2]TRACK
有破折号,所以我们不知道什么时候分开 [0]ARTIST
和 [2]TRACK
标记,所以正则表达式应该排除这个不要修改这个文件名。
- 发件人:'艺术家姓名 - 曲目名称专长'
- 收件人:'艺术家姓名 - 曲目名称专长'
[0]ARTIST
和 [2]TRACK
标记有破折号,所以我们不知道什么时候把它们分开,所以正则表达式应该排除这个不要修改这个文件名。
- 来自:'Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼'
- 致:'Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼'
[0]ARTIST
和 [2]TRACK
标记有破折号,而且 [3]FEAT_ARTIST
不存在,这里也无事可做。
- 来自:'Dj E-nergy C-21 - 我的超级英雄曲目!'
- 致:'Dj E-nergy C-21 - 我的超级英雄曲目!'
我希望这有助于了解我的需求。
我认为您唯一需要 realize/change 的是 "separator hyphen" 和 "embedded hyphens" 之间有明显的区别。即 none 的嵌入式连字符在两边都有空格(我预计;您需要验证这一点)。您需要做的就是将上面的正则表达式的开头从 \A([^-]?)\s-\s*
更改为 \A(.?)\s-\s+
...
我把你所有的文件名都输入到文本编辑器 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 (\[{]| (?![(\[{]))+)
和替换字符串
-
这些文件名被修改为不区分大小写全部替换为
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\.?) +(?:[^ (\[{]| (?![(\[{]))+)
替换字符串也是:
-
搜索字符串的解释:
^
...行首
\A
... 缓冲区开始
(.+) -
... 一个 greedy 表达式匹配任何字符 1 次或多次(换行符除外)直到 last 在标记组中出现 space破折号space 不包括 -
,这仍然会导致 整个表达式 .
的正匹配
(.+?)
... 非贪婪 表达式也在捕获组中匹配任何字符(换行符除外)一次或多次直到下一次出现space 和...
(?:featuring|feat\.?|ft\.?) +
... 单词 featuring
OR 缩写 feat
带或不带点 OR 缩写 ft
带或不带点 AND 1 个或多个 spaces.
(
... 第三个捕获组的开始。
(?:[^\r\n (\[{]| (?![(\[{]))+
...一个非标记组匹配
- 一个字符不是
- 回车符 return 或换行符(仅限 UE 搜索字符串),或
- 左括号,或
- 左方括号,或
- 左大括号
或
- a space 使用否定先行表达式检查下一个字符是否 not
- 左括号,或
- 左方括号,或
- 左大括号
一次或多次。换句话说,最后一个表达式匹配文件名结尾或 (
或 [
或 {
之前的所有内容,不包括留给这些字符的 space 以避免得到 spacespacedash after FEAT_ARTIST
after replace.
)
...终于结束了第三个捕获组。
编辑 1: 同样有效(在 UltraEdit 中)的是搜索字符串:
^(.+) - (.+?) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
除了 featuring.
之外,还可以使表达更容易一些。
编辑 2: 同样有效(在 UltraEdit 中)的是搜索字符串:
^((?:.(?! - ))+.) - ((?:.(?! - ))+) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
忽略所有包含两个 spacedashspace[=129 的行=] 留给 FEAT_ARTIST
.
如果当前字符之后的字符串不是 space破折号[,则此表达式使用否定先行逐字符匹配=92=]space。这允许用于第一个捕获组,它选择第一个 spacedash[ 左边的最后一个字符的字符串=167=],但对于第二个捕获组,不应再有 spacedashspace 因为这肯定会导致整个表达式的结果为负。
试试:
^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$
并使用替换为: Feat. -
我用 ReNamer 和 Regex101 试过了,如果有 -
(</code> + <code>-
+ </code>) in artist name, like <code>artist - name
, 但是如果标题部分有这样的片段,它会失败。
^(.+)\s+-\s+
部分在序列 space-dash-space 之前使用贪婪量词 .+
,它被视为艺术家姓名和曲目标题之间的分隔符。所以它会尽可能多地匹配,直到最后一次出现 -
,因此,它会 "ignore" 艺术家姓名中带有空格的破折号,但如果这样的话,它会出现无效匹配元素出现在曲目标题中。所以:
Artist - name - track title feat. someone
- 它将被匹配并且
修改妥当,
Artist name - track - title feat. someone
- 它会失败,如文本
将在最后一个破折号处拆分。
我使用 [fF](t|eat(uring)?)?\.?
代替 (ft[.\s]|feat[.\s]|featuring[.\s])
匹配相似,但应该工作得更快(它应该稍微限制回溯)。
在我的演示中,有一个 +
而不是 \s+
(如上),因为它会在演示中匹配多行,并显示无效结果,但在单行情况下,就像你的问题, 它应该可以正常工作。
在@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.
//
rgxPattern := '^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$'
rgxReplace := ' Feat. - '
// 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.
场景
我正在使用一个用 Delphi 编写并支持 pascal 脚本的第三方文件重命名软件:http://www.den4b.com/?x=products&product=renamer
该应用程序允许使用正则表达式来重命名文件。这意味着如果我需要用一个文件名做的事情不能仅使用一个 RegEx 来完成,那么我可以同时使用各种表达式或 pascal 脚本代码来容纳文件名,直到我可以根据需要正确格式化文件名问题或其他...
问题
我需要像下面这样格式化歌曲文件名,在这些文件名中,“...featuring artist”部分位于字符串的右侧,我需要匹配它并将其放在字符串的左侧。
- Carbin 和 Sirmark - 对不起壮举。七人
- Kristjan Cash Cash - 带我回家壮举。 Bebe Rexha(撤销混音)
为了便于理解,我们可以想象 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:()[]{}
我实际上使用这个正则表达式来做到这一点:
\A([^-]?)\s-\s*(.?)\s([([])?((ft[.\s]|feat[.\s]|featuring[.\s])[^(){}[]]*)([)]])?(.+)?\Z
替换为:
-
问题从这里开始,因为 [0]ARTIST
和 [2]TRACK
标记可能包含破折号,例如这个文件名:
- Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼
然后,如果我错了,请纠正我,但我认为它不可能以任何方式解决这个问题,因为机器无法预测何时将一个标记与另一个标记分开,什么是名称或什么不是,因为我不知道包含文件名的破折号的数量。
For that reason, instead of looking for ingenuos perfection that could cause bad filenames because the amount of dashes inside, I prefer to look for a filename exclusion solution, by limiting the dashes that the expression should match in the filename.
问题
以我上面显示的 RegEx 为例 extend/improve 它,我如何排除包含 [0]ARTIST
或带破折号的 [2]TRACK
标记的文件名?
...或者换句话说,当文件名包含超过 1 个破折号 before " 时,我如何告诉我的 RegEx 避免修改文件名...特色艺术家”部分? (不在之后)
基本上,Regex 应该确定 [1]DASH
是否在 [3]FEAT_ARTIST
之前被多次找到,如果是,则排除该文件名(不要修改它)
我知道如何限制 Regex 组的出现次数或多或少像这样 ([\-]){1}
以仅匹配 1 个破折号出现,但我不确定如何在表达式中实现它使用。
预期结果
只是一些随机的例子...
只有在 [3]FEAT_ARTIST
之前有一个破折号,这样我们就可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。
- 发件人:'Carbin & Sirmark - 对不起壮举。七人'
- 收件人:'Carbin & Sirmark Feat。 Sevener - 抱歉'
仅在 [3]FEAT_ARTIST
之前有一个破折号,因此我们可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。 [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
.
- 来自:'飞行设施 - 心脏病专长。 Owl 眼睛(蛇臀混音)'
- 收件人:'飞行设施专长。 Owl 眼睛 - 心脏病发作 (Snakehips Remix)'
仅在 [3]FEAT_ARTIST
之前有一个破折号,因此我们可以知道何时将 [0]ARTIST
与 [2]TRACK
标记分开。 [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
也包含破折号。
- 来自:'飞行设施 - 心脏病专长。 Owl眼睛[蛇--臀Remix]'
- 收件人:'飞行设施专长。 Owl眼睛-心脏病发作[蛇--臀Remix]'
仅在 [0]ARTIST
和 [2]TRACK
标记之间有一个破折号,但文件名没有 [3]FEAT_ARTIST
所以我们不碰它。
- 来自:'Fedde Le Grand - 电影'
- 收件人:'Fedde Le Grand - 电影'
仅在 [0]ARTIST
和 [2]TRACK
标记之间有一个破折号,但是 [3]FEAT_ARTIST
在 [1]DASH
之前,所以我们不碰它。
- 发件人:'Fedde Le Grand Feat。丹尼怀特 - 电影'
- 致:'Fedde Le Grand Feat。丹尼怀特 - 电影'
[0]ARTIST
有破折号,所以我们不知道什么时候分开 [0]ARTIST
和 [2]TRACK
标记,所以正则表达式应该排除这个不要修改这个文件名。
- 发件人:'艺术家姓名 - 曲目名称专长'
- 收件人:'艺术家姓名 - 曲目名称专长'
[2]TRACK
有破折号,所以我们不知道什么时候分开 [0]ARTIST
和 [2]TRACK
标记,所以正则表达式应该排除这个不要修改这个文件名。
- 发件人:'艺术家姓名 - 曲目名称专长'
- 收件人:'艺术家姓名 - 曲目名称专长'
[0]ARTIST
和 [2]TRACK
标记有破折号,所以我们不知道什么时候把它们分开,所以正则表达式应该排除这个不要修改这个文件名。
- 来自:'Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼'
- 致:'Dj E-nergy C-21 - 我的超级英雄曲目!壮举 Dj 屁眼'
[0]ARTIST
和 [2]TRACK
标记有破折号,而且 [3]FEAT_ARTIST
不存在,这里也无事可做。
- 来自:'Dj E-nergy C-21 - 我的超级英雄曲目!'
- 致:'Dj E-nergy C-21 - 我的超级英雄曲目!'
我希望这有助于了解我的需求。
我认为您唯一需要 realize/change 的是 "separator hyphen" 和 "embedded hyphens" 之间有明显的区别。即 none 的嵌入式连字符在两边都有空格(我预计;您需要验证这一点)。您需要做的就是将上面的正则表达式的开头从 \A([^-]?)\s-\s*
更改为 \A(.?)\s-\s+
...
我把你所有的文件名都输入到文本编辑器 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 (\[{]| (?![(\[{]))+)
和替换字符串
-
这些文件名被修改为不区分大小写全部替换为
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\.?) +(?:[^ (\[{]| (?![(\[{]))+)
替换字符串也是:
-
搜索字符串的解释:
^
...行首
\A
... 缓冲区开始
(.+) -
... 一个 greedy 表达式匹配任何字符 1 次或多次(换行符除外)直到 last 在标记组中出现 space破折号space 不包括 -
,这仍然会导致 整个表达式 .
(.+?)
... 非贪婪 表达式也在捕获组中匹配任何字符(换行符除外)一次或多次直到下一次出现space 和...
(?:featuring|feat\.?|ft\.?) +
... 单词 featuring
OR 缩写 feat
带或不带点 OR 缩写 ft
带或不带点 AND 1 个或多个 spaces.
(
... 第三个捕获组的开始。
(?:[^\r\n (\[{]| (?![(\[{]))+
...一个非标记组匹配
- 一个字符不是
- 回车符 return 或换行符(仅限 UE 搜索字符串),或
- 左括号,或
- 左方括号,或
- 左大括号
或
- a space 使用否定先行表达式检查下一个字符是否 not
- 左括号,或
- 左方括号,或
- 左大括号
一次或多次。换句话说,最后一个表达式匹配文件名结尾或 (
或 [
或 {
之前的所有内容,不包括留给这些字符的 space 以避免得到 spacespacedash after FEAT_ARTIST
after replace.
)
...终于结束了第三个捕获组。
编辑 1: 同样有效(在 UltraEdit 中)的是搜索字符串:
^(.+) - (.+?) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
除了 featuring.
之外,还可以使表达更容易一些。
编辑 2: 同样有效(在 UltraEdit 中)的是搜索字符串:
^((?:.(?! - ))+.) - ((?:.(?! - ))+) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)
忽略所有包含两个 spacedashspace[=129 的行=] 留给 FEAT_ARTIST
.
如果当前字符之后的字符串不是 space破折号[,则此表达式使用否定先行逐字符匹配=92=]space。这允许用于第一个捕获组,它选择第一个 spacedash[ 左边的最后一个字符的字符串=167=],但对于第二个捕获组,不应再有 spacedashspace 因为这肯定会导致整个表达式的结果为负。
试试:
^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$
并使用替换为: Feat. -
我用 ReNamer 和 Regex101 试过了,如果有 -
(</code> + <code>-
+ </code>) in artist name, like <code>artist - name
, 但是如果标题部分有这样的片段,它会失败。
^(.+)\s+-\s+
部分在序列 space-dash-space 之前使用贪婪量词 .+
,它被视为艺术家姓名和曲目标题之间的分隔符。所以它会尽可能多地匹配,直到最后一次出现 -
,因此,它会 "ignore" 艺术家姓名中带有空格的破折号,但如果这样的话,它会出现无效匹配元素出现在曲目标题中。所以:
Artist - name - track title feat. someone
- 它将被匹配并且 修改妥当,Artist name - track - title feat. someone
- 它会失败,如文本 将在最后一个破折号处拆分。
我使用 [fF](t|eat(uring)?)?\.?
代替 (ft[.\s]|feat[.\s]|featuring[.\s])
匹配相似,但应该工作得更快(它应该稍微限制回溯)。
在我的演示中,有一个 +
而不是 \s+
(如上),因为它会在演示中匹配多行,并显示无效结果,但在单行情况下,就像你的问题, 它应该可以正常工作。
在@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.
//
rgxPattern := '^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$'
rgxReplace := ' Feat. - '
// 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.