将驼峰式大小写更改为破折号分隔的小写字母的单个正则表达式

Single regex that changes camel-case to dash-separated lowercase

我正在尝试为 javascript import 语句编写 SublimeText snippet。我希望格式格式如下:

import MyFooBar from 'my-foo-bar';

我的正则表达式的输入是 MyFooBar,输出需要是 my-foo-bar。我在 Regex - CamelCase to lower case with underscores:

中找到了几乎有效的答案

Search for

((?<=.)[A-Z][a-zA-Z]*)|((?<=[a-zA-Z])\d+)

Replace with

-

答案说只使用 javascript 的 .toLowerCase() 方法进行小写,但 SublimeText 片段使用 perl,我对它了解最简单。快速搜索说对于小写,我可以在替换的开头使用 \L

/((?<=.)[A-Z][a-zA-Z0-9]*)|((?<=[a-zA-Z])\d+)/\L-/g

这适用于除第一段字符以外的所有字符,因此 MyFooBar 变为 My-foo-bar

我想也许我可以 运行 按顺序使用两个正则表达式,但是 perl 或 Sublime 都无法识别。

想法?

编辑:

当我说它使用 perl 时,我的意思是它使用 perl 正则表达式。据我所知,我实际上无法执行任意代码;我只能指定一个 perl 可以执行的正则表达式。

这是我的片段的全文:

<snippet>
    <content><![CDATA[
import ${1:module} from '${2:./path/}${1/((?<=.)[A-Z][a-zA-Z0-9]*)|((?<=[a-zA-Z])\d+)/\L-/g}';
]]></content>
    <!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
    <tabTrigger>import</tabTrigger>
    <!-- Optional: Set a scope to limit where the snippet will trigger -->
    <scope>source.js</scope>
</snippet>

丑陋(substr())但有效:

$x = "MyFooBar";
$x =~ s/(?:^|(?<=[a-z])(?=[A-Z]))(.)/-lc()/eg;
$x = substr($x, 1);
print $x;
// my-foo-bar

查看 ideone.com 上的演示。

这个花了我一些时间,但我相信它可以满足您的需求,所有这些都在一个正则表达式中:

use warnings;
use strict;

while (<DATA>){
    chomp;
    s/([[:upper:]].*?)(?=(?:[[:upper:]]|$))/$+[0]!=length($_) ? lc().'-' : lc()/ge;
    print "$_\n";
}

__DATA__
MyCamelCase
AVeryLongCamelCaseStringWMXThat

输出:

my-camel-case
a-very-long-camel-case-string-w-m-x-that

解释:它寻找一个大写字母,并将该字母与所有其他字母一起捕获到 </code> 中,直到它在 zero-width 前瞻中看到另一个大写字母或字符串结尾。在替换端,我们使用 <code>/e 修饰符,这意味着 right-hand 端是一个表达式(可执行代码)。如果最近匹配的末尾 ($+[0]) 小于字符串的长度,我们会做一个更小的 (lc()) 并附加一个 -。如果字符串的长度与最后一个匹配的末尾相同,我们将其小写并完成。

我将 RegEx 更改为更有用且可能更简单的内容。

** 已更新

<snippet>
    <content><![CDATA[
import ${1:module} from '${2:./path/}${1/(^[A-Z][a-z]+|[a-z])([A-Z])/\L-/g}';
]]></content>
    <!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
    <tabTrigger>import</tabTrigger>
    <scope>source.js</scope>
</snippet>