修复 RegEx 以正确捕获括号内的文本

Posted

技术标签:

【中文标题】修复 RegEx 以正确捕获括号内的文本【英文标题】:Fix RegEx to properly capture text inside parenthesis 【发布时间】:2016-06-03 21:33:29 【问题描述】:

场景


前段时间我问了一个在特定条件下格式化音乐文件名的问题:

RegEx pattern to limit dashes in these circumstances

但是,我发现接受的答案是错误的为时已晚,因为它可以捕获任何以“F”开头的单词。但这不是问题/问题,我只是通过恢复ft|feat|featuring OR 组来解决它。

所以最后从上面链接的问题中,我最终使用了这个表达式:

pattern := '^(.+)\s+-\s+(.+?)\s+(ft|feat|featuring)[\.\s]*([^([\])]+)(.+)?$' 
replace := '$1 Feat. $4 - $2$5' 

现在,有这些文件名要测试:

    黑海岸 - Trndsttr 黑海岸 - Trndsttr(羽毛) Black Coast - Trndsttr (Lucian Remix) Black Coast - Trndsttr (Feather) (Lucian Remix) 黑海岸 - Trndsttr 壮举。 M. Maggie 黑海岸 - Trndsttr (Feat. M. Maggie) 黑海岸 - Trndsttr 壮举。 M. Maggie(卢西恩混音) Black Coast - Trndsttr (Feat. M. Maggie) (Lucian Remix) Black Coast - Trndsttr (Lucian Remix) Feat。 M. Maggie Black Coast - Trndsttr (Lucian Remix) (Feat. M. Maggie) Black Coast - Trndsttr (Feather) (Lucian Remix) Feat. M. Maggie Black Coast - Trndsttr (Feather) (Lucian Remix) (Feat. M. Maggie) 黑海岸 - Trndsttr(羽毛)壮举。 M. Maggie(卢西恩混音) Black Coast - Trndsttr (Feather) (Feat. M. Maggie) (Lucian Remix) Black Coast - Trndsttr (Feather) (Feat. M. Maggie) Lucian Remix 黑海岸 - Trndsttr(羽毛)壮举。 M. Maggie Lucian 混音

预期结果如下:

(从 1 到 4 没有变化,16 是假设的误报,本质上与 5、9 和 11 相同。)

    黑海岸 - Trndsttr 黑海岸 - Trndsttr(羽毛) Black Coast - Trndsttr (Lucian Remix) Black Coast - Trndsttr (Feather) (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr 黑海岸壮举。 M. Maggie - Trndsttr 黑海岸壮举。 M. Maggie - Trndsttr (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Feather) (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Feather) (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Feather) (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Feather) (Lucian Remix) 黑海岸壮举。 M. Maggie - Trndsttr (Feather) Lucian Remix 黑海岸壮举。 M. Maggie Lucian Remix - Trndsttr (Feather)

问题


我提到的表达式适用于所有文件名,除了 Feat... 部分被分组在括号(或括号等)内的情况。

然后我尝试调整 RegEx 以适应聚合条件:

pattern := '^(.+)\s+-\s+(.+?)\s+([\[\(\])?\s*(ft|feat|featuring([\.])?\s+)((.+)[^\]\)\])?\s*(.+)?$'

但我结束了我的脑袋和遗漏的事情,因为它还捕获了第一个括号括起来和后面的字符直到最后。

我需要一些帮助。

问题


我如何修复/改进我的表达式以处理提到的文件名以获得上述预期结果?。

或者换句话说,我需要维护表达式的“结构”,但添加能够在 Feat... 部分位于括号/括号内时捕获它以正确格式化文件名.

PS:请记住,我使用的是 pascal-script 的 RegEx 语法及其限制(我不确定)。

重要编辑:

我发现具有此限制的软件的作者支持从其 pascal 脚本编辑器运行外部应用程序,因此我可以启动用 .Net 编写的 CLI 应用程序来执行正则表达式替换,然后我' m 现在在 C#/Vb.Net RegEx 电机改进下,很好!。

【问题讨论】:

【参考方案1】:

类似:

^(?P<artist>.+?(?=\s-\s))          # artist with pos. lookahead
\s-\s                              # space - space
(?P<title>.+?(?=(?:\(?Feat\.)|$))  # title with pos. lookahead 
\(?                                # optional open parenthesis
    (?P<artist2>Feat\.[^()\n]+)?   # artist2 with Feat. before
\)?                                # optional closing parenthesis
(?P<subtitle>.+)?$                 # optional subtitle

见a demo on regex101.com。 问题是破折号并不总是匹配(可能是一些额外的编程逻辑?)

【讨论】:

感谢您的回答和为设计表达式所做的努力......但正如我指定的那样,我使用的是 pascal-script,而不是 php 语法及其改进,在删除之前和之后,表达式无法运行编译器说的命名组无法识别修饰符(不完全是在哪里): ^(.+?(?=\s-\s))\s-\s(.+?(?=(?:(?Feat \.)|$))(?(Feat\.[^()\n]+)?)?(.+)?$,你的表达可以适应我的情况\语言?。跨度> 请忘记我所说的关于 pascal-script 的内容,现在我发现具有此限制的软件的作者支持从其 pascal-script 编辑器运行外部应用程序,所以我会开发一个用 C# 编写的简单应用程序,我将开始翻译 PHP 语法,我会来这里接受答案或揭露有关您评论的破折号的任何问题。谢谢大家! 考虑到我的需要,这是带有 .Net 语法的最终正则表达式:"^(?.+?(?=\s*-\s*))\s* -\s*(?.+?(?=(?:(?(ft|feat|featuring)\.)|$))(?(?<feat>(ft|feat|featuring)\. [^()\n]+)?)?(?<subtitle>.+)?$</subtitle></feat> " 和替换: "$artist $feat - $title$ subtitle”加上一个小的额外替换双空格。感谢您的回答!。 凭借你惊人的技能,如果你能通过避免额外的替换步骤来解决空格的小问题以提高性能,那就太好了......这个正则表达式将用于每天替换数千个文件名,并且只是初始化一个外部应用程序来执行每次更换会花费很多时间。我希望我没有要求太多!无论如何你的正则表达式都很棒。

以上是关于修复 RegEx 以正确捕获括号内的文本的主要内容,如果未能解决你的问题,请参考以下文章

捕获大括号内的内容

用于匹配嵌套括号内的特定文本的 C# 正则表达式

突出显示方括号内的文本(正则表达式?)Android kotlin

Emmet 缩写 - 元素标签内的文本

PHP/REGEX:获取括号内的字符串

Python:使用JSON API链接通过正则表达式显示命名捕获组