简体   繁体   English

使用preg_replace()将CamelCase转换为snake_case

[英]Using preg_replace() to convert CamelCase to snake_case

I have a method now that will convert my camel case strings to snake case, but it's broken into three calls of preg_replace() : 我现在有一个方法将我的驼峰案例字符串转换为蛇案例,但它分为三个preg_replace()调用:

public function camelToUnderscore($string, $us = "-")
{
    // insert hyphen between any letter and the beginning of a numeric chain
    $string = preg_replace('/([a-z]+)([0-9]+)/i', '$1'.$us.'$2', $string);
    // insert hyphen between any lower-to-upper-case letter chain
    $string = preg_replace('/([a-z]+)([A-Z]+)/', '$1'.$us.'$2', $string);
    // insert hyphen between the end of a numeric chain and the beginning of an alpha chain
    $string = preg_replace('/([0-9]+)([a-z]+)/i', '$1'.$us.'$2', $string);

    // Lowercase
    $string = strtolower($string);

    return $string;
}

I wrote tests to verify its accuracy, and it works properly with the following array of inputs ( array('input' => 'output') ): 我编写了测试来验证其准确性,并且它可以正常使用以下输入array('input' => 'output') ):

$test_values = [
    'foo'       => 'foo',
    'fooBar'    => 'foo-bar',
    'foo123'    => 'foo-123',
    '123Foo'    => '123-foo',
    'fooBar123' => 'foo-bar-123',
    'foo123Bar' => 'foo-123-bar',
    '123FooBar' => '123-foo-bar',
];

I'm wondering if there's a way to reduce my preg_replace() calls to a single line which will give me the same result. 我想知道是否有办法将我的preg_replace()调用减少到一行,这将给我相同的结果。 Any ideas? 有任何想法吗?

NOTE: Referring to this post , my research has shown me a preg_replace() regex that gets me almost the result I want, except it doesn't work on the example of foo123 to convert it to foo-123 . 注意: 参考这篇文章 ,我的研究我展示了一个preg_replace()正则表达式,它几乎得到了我想要的结果,除了它不能用于将foo123转换为foo-123的例子。

You can use lookarounds to do all this in a single regex: 你可以使用lookarounds在一个正则表达式中完成所有这些:

function camelToUnderscore($string, $us = "-") {
    return strtolower(preg_replace(
        '/(?<=\d)(?=[A-Za-z])|(?<=[A-Za-z])(?=\d)|(?<=[a-z])(?=[A-Z])/', $us, $string));
}

RegEx Demo RegEx演示

Code Demo 代码演示

RegEx Description: RegEx说明:

(?<=\d)(?=[A-Za-z])  # if previous position has a digit and next has a letter
|                    # OR
(?<=[A-Za-z])(?=\d)  # if previous position has a letter and next has a digit
|                    # OR
(?<=[a-z])(?=[A-Z])  # if previous position has a lowercase and next has a uppercase letter

Here is my two cents based on the duplicated post I flagged earlier. 这是我基于我之前标记的重复帖子的两分钱。 The accepted solution here is awesome. 这里接受的解决方案很棒。 I just wanted to try to solve it with what was shared : 我只想尝试用共享内容来解决它:

function camelToUnderscore($string, $us = "-") {
    return strtolower(preg_replace('/(?<!^)[A-Z]+|(?<!^|\d)[\d]+/', $us.'$0', $string));
}

Example : 示例:

Array
(
    [0] => foo
    [1] => fooBar
    [2] => foo123
    [3] => 123Foo
    [4] => fooBar123
    [5] => foo123Bar
    [6] => 123FooBar
)

foreach ($arr as $item) {
    echo camelToUnderscore($item);
    echo "\r\n";
}

Output : 输出:

 foo foo-bar foo-123 123-foo foo-bar-123 foo-123-bar 123-foo-bar 

Explanation : 说明:

(?<!^)[A-Z]+      // Match one or more Capital letter not at start of the string
|                 // OR
(?<!^|\d)[\d]+    // Match one or more digit not at start of the string

$us.'$0'          // Substitute the matching pattern(s)

online regex 在线正则表达式

The question is already solved so I won't say that I hope it helps but maybe someone will find this useful. 问题已经解决,所以我不会说我希望它有所帮助,但也许有人会觉得这很有用。


EDIT 编辑

There are limits with this regex : 这个正则表达式有限制:

foo123bar => foo-123bar
fooBARFoo => foo-barfoo

Thanks to @urban for pointed it out. 感谢@urban指出。 Here is his link with tests with the three solutions posted on this question : 以下是他在此问题上发布的三个解决方案的测试链接:

three solutions demo 三个解决方案演示

From a colleague: 来自同事:

$string = preg_replace(array($pattern1, $pattern2), $us.'$1', $string); might work 可能有用

My solution: 我的解决方案

public function camelToUnderscore($string, $us = "-")
{
    $patterns = [
        '/([a-z]+)([0-9]+)/i',
        '/([a-z]+)([A-Z]+)/',
        '/([0-9]+)([a-z]+)/i'
    ];
    $string = preg_replace($patterns, '$1'.$us.'$2', $string);

    // Lowercase
    $string = strtolower($string);

    return $string;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM