【问题标题】:Single regex that changes camel-case to dash-separated lowercase将驼峰大小写更改为破折号分隔小写的单个正则表达式
【发布时间】:2016-01-27 18:53:33
【问题描述】:

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

import MyFooBar from 'my-foo-bar';

我的正则表达式的输入是MyFooBar,输出需要是my-foo-bar。我找到了一个几乎适用于Regex - CamelCase to lower case with underscores的答案:

搜索

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

替换为

-$1$2

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

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

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

我想也许我可以依次运行两个正则表达式,但是 perl 或 Sublime 都无法识别。

想法?

编辑:

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

这是我的 sn-p 的全文:

<snippet>
    <content><![CDATA[
import ${1:module} from '${2:./path/}${1/((?<=.)[A-Z][a-zA-Z0-9]*)|((?<=[a-zA-Z])\d+)/\L-\1\2/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>

【问题讨论】:

  • 为什么必须成为一个正则表达式?这将更容易通过适当的搜索和替换功能来处理,perl 具有...
  • @cat 我只是在学习如何创建 sn-ps,但 sublimetext.info/docs/en/extensibility/… 只显示了一种替换方法。
  • @anubhava OPs 最后一句话是这里的问题。您运行 2 个正则表达式来纠正第一个字符上的“错误”,这显然不起作用。
  • 能否上传您当前的完整sn-p?
  • @revo 我已经更新了问题

标签: regex pcre sublimetext-snippet


【解决方案1】:

我将 RegEx 更改为更有用且可能更简单的东西。

** 更新

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

【讨论】:

  • 这将在我的模块文件名前添加一个-。我可以删除它,但这基本上是我现在必须做的,替换第一个大写字符。
  • @dfoverdx 哦,是的,但是当我这样做 enter 时,多余的破折号就会消失!
  • 奇怪的是它不适合我...事实上,当我按下回车键时,它在两个位置都用正则表达式的值替换了我输入的内容。
  • 如此接近。在我尝试“环境”之前,我认为它有效。如果没有第二个大写字母,则不会替换该单词。仅替换第一个字符不是大问题。唉,我认为这种特殊的努力是不可能的。
  • 可以通过将-\2 更改为(?2-\2) 来使其成为有条件的。完整的正则表达式行:import ${1:module} from '${2:./path/}${1/(^[A-Z][a-z]*|[a-z])([A-Z])?/\L\1(?2-\2)/g}';
【解决方案2】:

丑陋的 (substr()) 但有效:

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

ideone.com 上查看演示。

【讨论】:

  • 赞成,但是如果你传入 MyFooBarID 之类的东西呢?
【解决方案3】:

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

use warnings;
use strict;

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

__DATA__
MyCamelCase
AVeryLongCamelCaseStringWMXThat

输出:

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

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

【讨论】:

  • 这行不通,因为 Sublime sn-ps 实际上并没有解释 Perl——它们只是使用 PCRE 语法。
  • 我将它复制并粘贴到我的 sn-p 中并运行它。 import MyFooBar from './path/My[1]!=length$_-1 ? lcMy.'-' : lcMyFoo[1]!=length$_-1 ? lcFoo.'-' : lcFooBar[1]!=length$_-1 ? lcBar.'-' : lcBar'; 不错的尝试!
  • 啊,废话 :) 我错过了关于代码未执行的部分。
  • 嗯,这是我第一次使用$+[0]$-[0],所以至少我们中的一个人从中受益:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 1970-01-01
  • 2012-05-12
相关资源
最近更新 更多