您好,我正在尝试制作一个精彩的文本片段,我想 将camelCase 单词转换为snake_case。我确实知道有一些插件可以让你将字符串转换为snake_case,但我想通过sublime text snippets来做到这一点。
我有一个如下所示的片段。
<snippet>
<content><![CDATA[
/**
* ${TM_FILEPATH/^.+\/(\w+)\.php$/${1}/} belongs to many (many-to-many) ${1/^((.+)ies)|(.+[^s])s$/\u(?1$2y:$3)/}.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function $1()
{
return \$this->belongsToMany('App\\${1/^((.+)ies)|(.+[^s])s$/\u(?1$2y:$3)/}', '${TM_FILEPATH/^.+\/(\w+)\.php$/\l${1}/}_$1', '${TM_FILEPATH/^.+\/(\w+)\.php$/\l${1}/}_id', '${1/^((.+)ies)|(.+[^s])s$/\l(?1$2y:$3)/}_id');
}
]]></content>
<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<tabTrigger>btm</tabTrigger>
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<scope>source.php</scope>
<description>Eloquent belongsToMany() (pivot) relation</description>
</snippet>
作为输出,它给了我。
/**
* UserMessages belongs to many (many-to-many) Role.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles()
{
return $this->belongsToMany('App\Role', 'userMessages_roles', 'userMessages_id', 'role_id');
}
我想要的结果是 userMessages 成为 user_messages。 知道如何实现这一点。
非常感谢。
执行类似操作的代码片段示例如下,基于您的示例,但为了清晰起见进行了缩短(我还将范围更改为
embedding.php
,以便它会使用我用于 PHP 的语法触发)。您应该能够在较大的代码片段示例中根据您的需求进行调整。
<snippet>
<content><![CDATA[
// ${1/^([A-Z])|(?:([A-Z]))/(?1\l$1:)(?2_\l$2:)/g}
public function ${1}()
{
$0
}
]]></content>
<tabTrigger>btm</tabTrigger>
<scope>embedding.php</scope>
<description>Eloquent belongsToMany() (pivot) relation</description>
</snippet>
其基础可以在非官方文档的snippets页面中看到。代码片段中变量的扩展采用
${variable/regex/format_string/options}
的形式。正则表达式使用 boost 库正则表达式 和 格式字符串。
Boost 支持
(?Ntrue:false)
形式的条件替换,其中对于捕获组 N
,如果匹配捕获到某些内容,则替换文本为 true
,如果没有捕获到某些内容,则替换文本为 false
。
在这里,我们在正则表达式中使用交替来拥有两个捕获组,以便我们可以根据匹配的项目提供两种不同的替换。第一个捕获组捕获前导大写字符并将其转换为小写,而第二个捕获组(未锚定到行的开头)执行相同操作,并且还在匹配项之前添加下划线。
Perl 提供了
\L
修饰符来在替换时小写捕获。
捕获内容位于方括号 () 中,可以通过 $1、$2 等进行反向引用。
因此,所需要做的就是找到一个小写字符,后跟一个大写字符,然后该字符应该是小写的。
sub camel_case_to_underscore {
my $method_name = shift;
$method_name =~s /([a-z])([A-Z])/$1_\L$2/g;
return lcfirst $method_name;
}
g
标志会全局替换,因此会替换字符串中的所有匹配项。
请注意,此函数也会将字符串的第一个字母小写, 我想这就是你想要的。