如何将PascalCase转换为pascal_case?

问题描述 投票:104回答:28

如果我有:

$string = "PascalCase";

我需要

"pascal_case"

PHP是否为此提供了功能?

php camelcasing
28个回答
145
投票

试试这个尺码:

$tests = array(
  'simpleTest' => 'simple_test',
  'easy' => 'easy',
  'HTML' => 'html',
  'simpleXML' => 'simple_xml',
  'PDFLoad' => 'pdf_load',
  'startMIDDLELast' => 'start_middle_last',
  'AString' => 'a_string',
  'Some4Numbers234' => 'some4_numbers234',
  'TEST123String' => 'test123_string',
);

foreach ($tests as $test => $result) {
  $output = from_camel_case($test);
  if ($output === $result) {
    echo "Pass: $test => $result\n";
  } else {
    echo "Fail: $test => $result [$output]\n";
  }
}

function from_camel_case($input) {
  preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
  $ret = $matches[0];
  foreach ($ret as &$match) {
    $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
  }
  return implode('_', $ret);
}

输出:

Pass: simpleTest => simple_test
Pass: easy => easy
Pass: HTML => html
Pass: simpleXML => simple_xml
Pass: PDFLoad => pdf_load
Pass: startMIDDLELast => start_middle_last
Pass: AString => a_string
Pass: Some4Numbers234 => some4_numbers234
Pass: TEST123String => test123_string

这实现了以下规则:

  1. 以小写字母开头的序列必须后跟小写字母和数字;
  2. 以大写字母开头的序列可以跟随: 一个或多个大写字母和数字(后跟字符串的结尾或大写字母后跟小写字母或数字,即下一个序列的开头);要么 一个或多个小写字母或数字。

4
投票

根本不是花哨,而是简单快速的地狱:

function uncamelize($str) 
{
    $str = lcfirst($str);
    $lc = strtolower($str);
    $result = '';
    $length = strlen($str);
    for ($i = 0; $i < $length; $i++) {
        $result .= ($str[$i] == $lc[$i] ? '' : '_') . $lc[$i];
    }
    return $result;
}

echo uncamelize('HelloAWorld'); //hello_a_world

4
投票

“CamelCase”改为“camel_case”:

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $camel);
    $snake = strtolower($snake);
    $snake = ltrim($snake, '_');
    return $snake;
}

要么:

function camelToSnake($camel)
{
    $snake = preg_replace_callback('/[A-Z]/', function ($match){
        return '_' . strtolower($match[0]);
    }, $camel);
    return ltrim($snake, '_');
}

3
投票

可以在Alchitect源中找到不使用正则表达式的版本:

decamelize($str, $glue='_')
{
    $counter  = 0;
    $uc_chars = '';
    $new_str  = array();
    $str_len  = strlen($str);

    for ($x=0; $x<$str_len; ++$x)
    {
        $ascii_val = ord($str[$x]);

        if ($ascii_val >= 65 && $ascii_val <= 90)
        {
            $uc_chars .= $str[$x];
        }
    }

    $tok = strtok($str, $uc_chars);

    while ($tok !== false)
    {
        $new_char  = chr(ord($uc_chars[$counter]) + 32);
        $new_str[] = $new_char . $tok;
        $tok       = strtok($uc_chars);

        ++$counter;
    }

    return implode($new_str, $glue);
}

3
投票

所以这是一个单行:

strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));

3
投票

qazxsw poi提供了一种将字符串从camelcase转换为snakecase的方法。

danielstjules/Stringy

3
投票

Laravel 5.6提供了一种非常简单的方法:

s('TestUCase')->underscored(); // 'test_u_case'

它的作用:如果它看到给定字符串中至少有一个大写字母,它使用 /** * Convert a string to snake case. * * @param string $value * @param string $delimiter * @return string */ public static function snake($value, $delimiter = '_'): string { if (!ctype_lower($value)) { $value = strtolower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value)); } return $value; } 搜索任何字符(positive lookahead),后跟大写字母(.)。然后用它的值替换找到的字符,然后是分隔符(?=[A-Z])


2
投票

来自rails的直接端口(减去它们对::或首字母缩略词的特殊处理)将是

_

知道PHP,这将比在此处给出的其他答案中发生的手动解析更快。缺点是你没有选择使用什么作为单词之间的分隔符,但这不是问题的一部分。

还要检查function underscore($word){ $word = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','\1_\2', $word); $word = preg_replace('#([a-z\d])([A-Z])#', '\1_\2', $word); return strtolower(strtr($word, '-', '_')); }

请注意,这适用于ASCII标识符。如果您需要使用ASCII范围之外的字符,请使用relevant rails source code的'/ u'修饰符使用preg_match


2
投票

这是我对一个六年之久的问题的贡献,上帝知道有多少答案......

它会将提供的字符串中所有在camelcase中的单词转换为snakecase。例如,“SuperSpecialAwesome和FizBuzzκαιΚάτιΑκόμα”将被转换为“super_special_awesome以及fizz_buzzκαι_κάτι_ακόμα”。

mb_strtolower

2
投票

Yii2具有不同的功能,可以从CamelCase中创建单词snake_case。

mb_strtolower(
    preg_replace_callback(
        '/(?<!\b|_)\p{Lu}/u',
        function ($a) {
            return "_$a[0]";
        },
        'SuperSpecialAwesome'
    )
);

1
投票
    /**
     * Converts any "CamelCased" into an "underscored_word".
     * @param string $words the word(s) to underscore
     * @return string
     */
    public static function underscore($words)
    {
        return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $words));
    }

130
投票

一个较短的解决方案:类似于编辑器的简化正则表达式并修复“尾随下划线”问题:

$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));

PHP Demo | Regex Demo


请注意,像SimpleXML这样的情况将使用上述解决方案转换为simple_x_m_l。这也可以被认为是骆驼案例符号的错误用法(正确的是SimpleXml),而不是算法的错误,因为这种情况总是模棱两可的 - 即使将大写字符分组到一个字符串(simple_xml),这样的算法总会在其他情况下失败边缘情况如XMLHTMLConverter或单字母附近的缩写等。如果你不介意(相当罕见的)边缘情况并想要正确处理SimpleXML,你可以使用一些更复杂的解决方案:

$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');

PHP Demo | Regex Demo


1
投票

有一个function camel2snake($name) { $str_arr = str_split($name); foreach ($str_arr as $k => &$v) { if (ord($v) >= 64 && ord($v) <= 90) { // A = 64; Z = 90 $v = strtolower($v); $v = ($k != 0) ? '_'.$v : $v; } } return implode('', $str_arr); } 提供此功能:

library

1
投票

如果您使用Laravel框架,则只能使用SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case" 方法。


1
投票

1
投票

这是一个较短的方法:

$str = 'FooBarBaz';

return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz

1
投票

如何在不使用正则表达式的情况下去除驼峰:

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}

编辑:

我将如何在2019年这样做:

function decamelize($str, $glue = '_') {
    $capitals = [];
    $replace  = [];

    foreach(str_split($str) as $index => $char) {
        if(!ctype_upper($char)) {
            continue;
        }

        $capitals[] = $char;
        $replace[]  = ($index > 0 ? $glue : '') . strtolower($char);
    }

    if(count($capitals) > 0) {
        return str_replace($capitals, $replace, $str);
    }

    return $str;
}

当PHP 7.4发布时:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
        return $glue . strtolower($matches[0]);
    }, $str);
}

1
投票

简短解决方案

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}

0
投票

使用Zend $subject = "PascalCase"; echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject)); 的Filter类很容易:

Word Filters

----- ----- underscoreToCamelCase

simple_test >>> SimpleTest

容易>>>容易

html >>> Html

simple_xml >>> SimpleXml

pdf_load >>> PdfLoad

start_middle_last >>> StartMiddleLast

字符串>>>字符串

some4_numbers234 >>> Some4Numbers234

test123 string >>> Test123 String

----- ----- camelCaseToUnderscore

simpleTest >>> simple_test

容易>>>容易

HTML >>> html

simpleXML >>> simplexml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

字符串>>>一个字符串

Some4Numbers234 >>> some4_numbers234

TEST123字符串>>> test123字符串


0
投票

这里最糟糕的答案是如此接近最好(使用框架)。不要,只需看看源代码。看看一个完善的框架使用什么将是一个更可靠的方法(尝试和测试)。 Zend框架有一些符合您需求的文字过滤器。 <?php namespace MyNamespace\Utility; use Zend\Filter\Word\CamelCaseToUnderscore; use Zend\Filter\Word\UnderscoreToCamelCase; class String { public function test() { $underscoredStrings = array( 'simple_test', 'easy', 'html', 'simple_xml', 'pdf_load', 'start_middle_last', 'a_string', 'some4_numbers234', 'test123_string', ); $camelCasedStrings = array( 'simpleTest', 'easy', 'HTML', 'simpleXML', 'PDFLoad', 'startMIDDLELast', 'AString', 'Some4Numbers234', 'TEST123String', ); echo PHP_EOL . '-----' . 'underscoreToCamelCase' . '-----' . PHP_EOL; foreach ($underscoredStrings as $rawString) { $filteredString = $this->underscoreToCamelCase($rawString); echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL; } echo PHP_EOL . '-----' . 'camelCaseToUnderscore' . '-----' . PHP_EOL; foreach ($camelCasedStrings as $rawString) { $filteredString = $this->camelCaseToUnderscore($rawString); echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL; } } public function camelCaseToUnderscore($input) { $camelCaseToSeparatorFilter = new CamelCaseToUnderscore(); $result = $camelCaseToSeparatorFilter->filter($input); $result = strtolower($result); return $result; } public function underscoreToCamelCase($input) { $underscoreToCamelCaseFilter = new UnderscoreToCamelCase(); $result = $underscoreToCamelCaseFilter->filter($input); return $result; } }

这是我从源代码改编的几种方法。

Source

0
投票

开源TurboCommons库在StringUtils类中包含一个通用的formatCase()方法,它允许您将字符串转换为许多常见的案例格式,如CamelCase,UpperCamelCase,LowerCamelCase,snake_case,Title Case等等。

function CamelCaseToSeparator($value,$separator = ' ') { if (!is_scalar($value) && !is_array($value)) { return $value; } if (defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1) { $pattern = ['#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#']; $replacement = [$separator . '\1', $separator . '\1']; } else { $pattern = ['#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#']; $replacement = ['\1' . $separator . '\2', $separator . '\1']; } return preg_replace($pattern, $replacement, $value); } function CamelCaseToUnderscore($value){ return CamelCaseToSeparator($value,'_'); } function CamelCaseToDash($value){ return CamelCaseToSeparator($value,'-'); } $string = CamelCaseToUnderscore("CamelCase");

要使用它,请将phar文件导入您的项目并:

https://github.com/edertone/TurboCommons

-1
投票

如果你可以开始:

use org\turbocommons\src\main\php\utils\StringUtils;

echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);

// will output 'camel_Case'

然后你可以转换到任何一种情况只是:

$string = 'Camel_Case'; // underscore or any other separator...

或任何其他情况:

$pascal = str_replace("_", "", $string);
$snake = strtolower($string);

32
投票

一个简洁的解决方案,可以处理一些棘手的用例:

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}

可以处理所有这些情况:

simpleTest => simple_test
easy => easy
HTML => html
simpleXML => simple_xml
PDFLoad => pdf_load
startMIDDLELast => start_middle_last
AString => a_string
Some4Numbers234 => some4_numbers234
TEST123String => test123_string
hello_world => hello_world
hello__world => hello__world
_hello_world_ => _hello_world_
hello_World => hello_world
HelloWorld => hello_world
helloWorldFoo => hello_world_foo
hello-world => hello-world
myHTMLFiLe => my_html_fi_le
aBaBaB => a_ba_ba_b
BaBaBa => ba_ba_ba
libC => lib_c

你可以在这里测试这个功能:http://syframework.alwaysdata.net/decamelize


24
投票

来自Ruby的String#camelizeString#decamelize

function decamelize($word) {
  return preg_replace(
    '/(^|[a-z])([A-Z])/e', 
    'strtolower(strlen("\\1") ? "\\1_\\2" : "\\2")',
    $word 
  ); 
}

function camelize($word) { 
  return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word); 
}

上述解决方案可能遗漏的一个技巧是'e'修饰符,它使preg_replace将替换字符串评估为PHP代码。


21
投票

Symfony Serializer Component有一个CamelCaseToSnakeCaseNameConverter有两种方法normalize()denormalize()。这些可以使用如下:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

echo $nameConverter->normalize('camelCase');
// outputs: camel_case

echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase

20
投票

这里的大多数解决方案都很重要这是我使用的:

$underscored = strtolower(
    preg_replace(
        ["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"], 
        ["_$1", "_$1_$2"], 
        lcfirst($camelCase)
    )
);

“CamelCASE”转换为“camel_case”

  • lcfirst($camelCase)将降低第一个字符(避免'CamelCASE'转换输出以下划线开头)
  • [A-Z]找到大写字母
  • +会将每个连续的大写视为一个单词(避免将'CamelCASE'转换为camel_C_A_S_E)
  • 第二种模式和替代是ThoseSPECCases - > those_spec_cases而不是those_speccases
  • strtolower([…])将输出转为小写

17
投票

php没有为这个afaik提供内置函数,但这是我使用的

function uncamelize($camel,$splitter="_") {
    $camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
    return strtolower($camel);

}

可以在函数调用中指定拆分器,因此可以像这样调用它

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"

8
投票
header('content-type: text/html; charset=utf-8');
$separated = preg_replace('%(?<!^)\p{Lu}%usD', '_$0', 'AaaaBbbbCcccDdddÁáááŐőőő');
$lower = mb_strtolower($separated, 'utf-8');
echo $lower; //aaaa_bbbb_cccc_dddd_áááá_őőőő

6
投票

如果您正在寻找PHP 5.4版本,稍后回答这里是代码:

function decamelize($word) {
      return $word = preg_replace_callback(
        "/(^|[a-z])([A-Z])/",
        function($m) { return strtolower(strlen($m[1]) ? "$m[1]_$m[2]" : "$m[2]"); },
        $word
    );

}
function camelize($word) {
    return $word = preg_replace_callback(
        "/(^|_)([a-z])/",
        function($m) { return strtoupper("$m[2]"); },
        $word
    );

} 
© www.soinside.com 2019 - 2024. All rights reserved.