Как преобразовать CamelCase в camel_case?

Если бы у меня было:

$string = "CamelCase"; 

мне нужно

 "camel_case" 

Предлагает ли PHP функцию для этой цели?

Solutions Collecting From Web of "Как преобразовать CamelCase в camel_case?"

Попробуйте это для размера:

 $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 

Это реализует следующие правила:

  1. Последовательность, начинающаяся с строчной буквы, должна сопровождаться строчными буквами и цифрами;
  2. Последовательность, начинающаяся с прописной буквы, может сопровождаться:
    • одну или несколько заглавных букв и цифр (за которыми следует либо конец строки, либо буква верхнего регистра, за которой следует строчная буква или цифра, т.е. начало следующей последовательности); или
    • одна или несколько строчных букв или цифр.

Более короткое решение: аналогично редактору с упрощенным регулярным выражением и исправлению проблемы «trailing-underscore»:

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

Демо-версия PHP | Демо-версия Regex


Обратите внимание, что такие случаи, как SimpleXML будут преобразованы в simple_x_m_l используя указанное выше решение. Это также можно считать неправильным использованием нотации верблюда (правильный был бы SimpleXml ), а не ошибкой алгоритма, поскольку такие случаи всегда неоднозначны – даже путем группировки прописных символов в одну строку ( simple_xml ) такой алгоритм всегда терпит неудачу в других такие как XMLHTMLConverter или однобуквенные слова вблизи аббревиатур и т. д. Если вы не возражаете о (довольно редких) случаях SimpleXML и хотите правильно обрабатывать SimpleXML , вы можете использовать немного более сложное решение:

 $output = ltrim(strtolower(preg_replace('/[AZ]([AZ](?![az]))*/', '_$0', $input)), '_'); 

Демо-версия PHP | Демо-версия Regex

Портировано из Ruby's 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); } 

Один трюк, описанный выше, может быть пропущен – это модификатор 'e', ​​который заставляет preg_replace оценивать заменяемую строку как PHP-код.

Большинство решений здесь чувствуют себя тяжело. Вот что я использую:

 $underscored = strtolower( preg_replace( ["/([AZ]+)/", "/_([AZ]+)([AZ][az])/"], ["_$1", "_$1_$2"], lcfirst($camelCase) ) ); 

«CamelCASE» преобразуется в «camel_case»

  • lcfirst($camelCase) опустит первый символ (избегает преобразованный вывод CamelCASE для начала с подчеркивания)
  • [AZ] находит заглавные буквы
  • + будет обрабатывать каждый последовательный прописный слот как слово (избегает «CamelCASE» для преобразования в camel_C_A_S_E)
  • Второй шаблон и замена для тех ThoseSPECCases -> those_spec_cases вместо those_speccases
  • strtolower([…]) превращает вывод в strtolower([…])

Краткое решение и может обрабатывать некоторые сложные варианты использования:

 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 

Вы можете проверить эту функцию здесь: 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" 

Компонент Serializer 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_áááá_őőőő 

(Принятое «решение» – это эпический провал …)

Не фантазия вообще, но простая и быстрая, как черт:

 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 ); } 

Версия, не использующая регулярное выражение, может быть найдена в источнике 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); } 

Итак, вот однострочный:

 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, это будет быстрее, чем ручной синтаксический анализ, который происходит в других ответах, приведенных здесь. Недостатком является то, что вы не можете выбрать, что использовать в качестве разделителя между словами, но это не было частью вопроса.

Также проверьте соответствующий исходный код рельсов

Обратите внимание, что это предназначено для использования с идентификаторами ASCII. Если вам нужно сделать это с символами вне диапазона ASCII, используйте модификатор '/ u' для preg_match и используйте mb_strtolower .

danielstjules / Stringy предлогает метод преобразования строки из верблюда в snakecase.

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

Вот мой вклад в шестилетний вопрос, когда бог знает, сколько ответов …

Он преобразует все слова в предоставленной строке, которые находятся в camelcase, чтобы snakecase. Например, «SuperSpecialAwesome, а также FizBuzz καιΚάτιΑκόμα» будут преобразованы в «super_special_awesome, а также fizz_buzz και_κάτι_ακόμα».

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

Это то, что я использую для декамелизации метода:

 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); } 

Существует библиотека, обеспечивающая эту функциональность:

 SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case" 

Легко использовать классы фильтра Zend Word Filters :

 <?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

startMIDDLastast >>> start_middle_last

AString >>> a_string

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string

Худший ответ здесь был настолько близок к тому, чтобы быть лучшим (использовать рамки). НЕТ НЕТ, просто взгляните на исходный код. видя, что использует хорошо зарекомендовавшие себя рамки, будет гораздо более надежным подходом (испытанным и испытанным). В системе Zend есть фильтры слов, которые соответствуют вашим потребностям. Источник .

вот несколько методов, которые я адаптировал из источника.

 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 framework, вы можете использовать только метод snake_case () .

Библиотека TurboCommons с открытым исходным кодом содержит метод formatCase () общего назначения внутри класса StringUtils, который позволяет конвертировать строку во множество распространенных форматов case, таких как 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 

«CamelCase» – «camel_case»:

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

или:

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

ЕСЛИ вы можете начать с:

 $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