如何将CamelCase转换为camel_case?
如果我有:
$string = "CamelCase";
我需要
"camel_case"
PHP为此提供了一个函数吗?
试试这个大小:
$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('!([AZ][A-Z0-9]*(?=$|[AZ][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
这实现了以下规则:
- 以小写字母开头的序列后面必须跟着小写字母和数字;
- 以大写字母开头的序列后面可以是:
- 一个或多个大写字母和数字(后跟string的结尾或大写字母后跟小写字母或数字,即下一个序列的开始); 要么
- 一个或多个小写字母或数字。
较短的解决scheme:类似于编辑器的简化正则expression式,并修复“尾部 – 下划线”问题:
$output = strtolower(preg_replace('/(?<!^)[AZ]/', '_$0', $input));
PHP演示 | 正则expression式演示
请注意,使用上述解决scheme,像SimpleXML
这样的情况将被转换为simple_x_m_l
。 这也可以被认为是错误的使用骆驼案例符号(正确的将是SimpleXml
),而不是algorithm的错误,因为这种情况总是含糊不清 – 即使通过将大写字符分组到一个string( simple_xml
),这样的algorithm总是会失败如XMLHTMLConverter
或缩写附近的单字母单词等。如果您不介意(非常less见的)边界情况并想正确处理SimpleXML
,则可以使用更复杂一些的解决scheme:
$output = ltrim(strtolower(preg_replace('/[AZ]([AZ](?![az]))*/', '_$0', $input)), '_');
PHP演示 | 正则expression式演示
从Ruby的String#camelize
和String#decamelize
。
function decamelize($word) { return preg_replace( '/(^|[az])([AZ])/e', 'strtolower(strlen("\\1") ? "\\1_\\2" : "\\2")', $word ); } function camelize($word) { return preg_replace('/(^|_)([az])/e', 'strtoupper("\\2")', $word); }
上面的解决scheme可能会错过的一个技巧是导致preg_replace
将replacestring评估为PHP代码的'e'修饰符。
这里的大部分解决scheme都是手足无措 以下是我使用的:
$underscored = strtolower( preg_replace( ["/([AZ]+)/", "/_([AZ]+)([AZ][az])/"], ["_$1", "_$1_$2"], lcfirst($camelCase) ) );
“CamelCASE”被转换为“camel_case”
-
lcfirst($camelCase)
会降低第一个字符(避免'CamelCASE'转换后的输出以下划线开头) -
[AZ]
find大写字母 -
+
会将每个连续的大写字母视为一个单词(避免将“CamelCASE”转换为camel_C_A_S_E) - 第二种模式和replace是为
ThoseSPECCases
– >those_spec_cases
而不是those_speccases
-
strtolower([…])
将输出转为小写
一个简洁的解决scheme,可以处理一些棘手的用例:
function decamelize($string) { return strtolower(preg_replace(['/([az\d])([AZ])/', '/([^_])([AZ][az])/'], '$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
你可以在这里testing这个函数: http : //syframework.alwaysdata.net/decamelize
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"
Symfony串行器组件有一个CamelCaseToSnakeCaseNameConverter ,它有两个方法normalize()
和denormalize()
。 这些可以使用如下:
$nameConverter = new CamelCaseToSnakeCaseNameConverter(); echo $nameConverter->normalize('camelCase'); // outputs: camel_case echo $nameConverter->denormalize('snake_case'); // outputs: snakeCase
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_áááá_őőőő
(被接受的“解决scheme”是一个史诗般的失败…)
一点也不喜欢,只是简单而迅速:
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
如果你正在寻找一个PHP 5.4版本,以后的答案是代码:
function decamelize($word) { return $word = preg_replace_callback( "/(^|[az])([AZ])/", function($m) { return strtolower(strlen($m[1]) ? "$m[1]_$m[2]" : "$m[2]"); }, $word ); } function camelize($word) { return $word = preg_replace_callback( "/(^|_)([az])/", function($m) { return strtoupper("$m[2]"); }, $word ); }
一个不使用正则expression式的版本可以在Alchitect来源find:
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); }
所以这是一个单行的:
strtolower(preg_replace('/(?|([az\d])([AZ])|([^\^])([AZ][az]))/', '$1_$2', $string));
从铁路直接港口(减去他们的特殊处理::或缩写)将是
function underscore($word){ $word = preg_replace('#([AZ\d]+)([AZ][az])#','\1_\2', $word); $word = preg_replace('#([az\d])([AZ])#', '\1_\2', $word); return strtolower(strtr($word, '-', '_')); }
了解PHP,这将比在这里给出的其他答案中发生的手动parsing更快。 缺点是你不能select用什么来作为单词之间的分隔符,但这不是问题的一部分。
还要检查相关的rails源代码
请注意,这是为了与ASCII标识符一起使用。 如果您需要使用ASCII范围以外的字符,请使用“/ u”修饰符进行preg_match
并使用mb_strtolower
。
danielstjules / Stringy提供了一种将camel转换成蛇形的方法。
s('TestUCase')->underscored(); // 'test_u_case'
这是我对六岁的问题的贡献,上帝知道有多less个答案…
它会将提供的string中的所有单词都转换为蛇形。 例如“SuperSpecialAwesome和FizBuzzκαιΚάτιΑκόμα”将被转换为“super_special_awesome和fizz_buzzκαι_κάτι_ακόμα”。
mb_strtolower( preg_replace_callback( '/(?<!\b|_)\p{Lu}/u', function ($a) { return "_$a[0]"; }, 'SuperSpecialAwesome' ) );
这就是我用于方法decamelization:
function decamelize($str, $glue='_') { $capitals = array(); $replace = array(); foreach(str_split($str) as $index => $char) { if(ord($char) >= 65 && ord($char) <= 90) { $capitals[] = $char; $replace[] = ($index > 0 ? $glue : '').strtolower($char); } } if(sizeof($capitals)) return str_replace($capitals, $replace, $str); return $str; }
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); }
有一个库提供这个function:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
使用Zend Word Filters的Filter类很容易:
<?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; } }
—– —– underscoreToCamelCase
simple_test >>> SimpleTest
容易>>>简单
html >>> Html
simple_xml >>> SimpleXml
pdf_load >>> PdfLoad
start_middle_last >>> StartMiddleLast
a_string >>> AString
some4_numbers234 >>> Some4Numbers234
test123_string >>> Test123String
—– —– camelCaseToUnderscore
simpleTest >>> simple_test
容易>>>
HTML >>> html
simpleXML >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLelast >>> start_middle_last
AString >>> a_string
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
这里最糟糕的答案是如此接近最好(使用框架)。 不,不要,只要看看源代码。 看到一个完善的框架使用什么是一个更可靠的方法(尝试和testing)。 Zend框架有一些适合您需要的词语filter。 来源 。
这里有几个我从源头上改编的方法。
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 = ['#(?<=(?:[AZ]))([AZ]+)([AZ][az])#', '#(?<=(?:[a-z0-9]))([AZ])#']; $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");
如果你使用Laravel框架,你可以使用snake_case()方法。
开源的TurboCommons库在StringUtils类中包含一个通用的formatCase()方法,它允许你将一个string转换成许多常见格式,比如CamelCase,UpperCamelCase,LowerCamelCase,snake_case,Title Case等等。
https://github.com/edertone/TurboCommons
要使用它,导入phar文件到您的项目和:
use org\turbocommons\src\main\php\utils\StringUtils; echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE); // will output 'camel_Case'
$str = 'FooBarBaz'; return strtolower(preg_replace('~(?<=\\w)([AZ])~', '_$1', $str)); // foo_bar_baz
如果你可以开始:
$string = 'Camel_Case'; // underscore or any other separator...
那么你可以转换为任何一种情况只是:
$pascal = str_replace("_", "", $string); $snake = strtolower($string);
或者任何其他情况:
$capitalized = str_replace("_", " ", $string); // Camel Case $constant = strtoupper($string); // CAMEL_CASE $train = str_replace("_", "-", $snake); // camel-case