Как конвертировать CamelCase в camel case?
Если бы я имел:
$string = "CamelCase";
мне нужно
"camel_case"
PHP предлагает функцию для этой цели?
27 ответов:
Попробуй вот это:
$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
это реализует следующие правила:
- последовательность, начинающаяся со строчной буквы, должна сопровождаться строчными буквами и цифрами;
- последовательность, начинающаяся с прописной буквы может сопровождаться либо:
- одна или несколько прописных букв и цифр (за которыми следует либо конец строки, либо заглавная буква, за которой следует строчная буква или цифра, т. е. начало следующей последовательности); или
- одна или несколько строчных букв или цифр.
более короткое решение: аналогично редактора один с упрощенным регулярным выражением и фиксацией проблемы "трейлинг-подчеркивания":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_', $input));
обратите внимание, что случаи, как
SimpleXML
будет преобразовано вsimple_x_m_l
используя вышеуказанное решение. Это также можно считать неправильным использованием обозначения случая верблюда (правильно было быSimpleXml
), а не ошибка алгоритма, поскольку такие случаи всегда неоднозначны - даже путем группировки прописных символов в одну строку (simple_xml
) такой алгоритм всегда будет терпеть неудачу в других случаях, какXMLHTMLConverter
или однобуквенные слова рядом с аббревиатурами и т. д. Если вы не возражаете против (довольно редких) крайних случаев и хотите обрабатыватьSimpleXML
правильно, вы можете использовать немного более сложное решение:$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_', $input)), '_');
краткое решение и может обрабатывать некоторые сложные случаи использования:
function decamelize($string) { return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '_', $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
портирован с Руби
String#camelize
иString#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-код.
большинство решений здесь чувствуют себя тяжелыми руками. Вот что я использую:
$underscored = strtolower( preg_replace( ["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"], ["_", "__"], lcfirst($camelCase) ) );
"CamelCASE" преобразуется в"camel_case"
lcfirst($camelCase)
понизит первый символ (избегает' CamelCASE ' преобразованный выход, чтобы начать с подчеркивания)[A-Z]
находит заглавные буквы+
будет рассматривать каждый последовательный верхний регистр как слово (избегает 'CamelCASE' для преобразования в camel_C_A_S_E)- вторая картина и замена для
ThoseSPECCases
->those_spec_cases
вместоthose_speccases
strtolower([…])
переводит вывод в нижний регистр
The Symfony Serializer Component есть CamelCaseToSnakeCaseNameConverter это имеет два метода
normalize()
иdenormalize()
. Они могут быть использованы следующим образом:$nameConverter = new CamelCaseToSnakeCaseNameConverter(); echo $nameConverter->normalize('camelCase'); // outputs: camel_case echo $nameConverter->denormalize('snake_case'); // outputs: snakeCase
php не предлагает встроенную функцию для этого afaik, но вот что я использую
function uncamelize($camel,$splitter="_") { $camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'', $camel)); return strtolower($camel); }
разделитель может быть указан в вызове функции, так что вы можете назвать его так
$camelized="thisStringIsCamelized"; echo uncamelize($camelized,"_"); //echoes "this_string_is_camelized" echo uncamelize($camelized,"-"); //echoes "this-string-is-camelized"
header('content-type: text/html; charset=utf-8'); $separated = preg_replace('%(?<!^)\p{Lu}%usD', '_', '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( "/(^|[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 ); }
"CamelCase" в "camel_case":
function camelToSnake($camel) { $snake = preg_replace('/[A-Z]/', '_', $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, '_'); }
версия, которая не использует регулярное выражение, может быть найдена в 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('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '_', $string));
danielstjules / Stringy обеспечивает надежное способ для преобразования строки из верблюжьего до snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
прямой порт от rails (минус их специальная обработка Для:: или аббревиатур) будет
function underscore($word){ $word = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','_', $word); $word = preg_replace('#([a-z\d])([A-Z])#', '_', $word); return strtolower(strtr($word, '-', '_')); }
зная PHP, это будет быстрее, чем ручной разбор, который происходит в других ответах, приведенных здесь. Недостатком является то, что вы не можете выбрать, что использовать в качестве разделителя между словами, но это не было частью вопроса.
проверьте соответствующий исходный код rails
обратите внимание, что это предназначено для использования с ASCII идентификаторы. Если вам нужно сделать это с символами вне диапазона ASCII, используйте модификатор '/u ' для
preg_match
и использоватьmb_strtolower
.
вот мой вклад в шестилетний вопрос с Бог знает сколько ответов...
он преобразует все слова в предоставленной строке, которые находятся в camelcase в snakecase. Например "SuperSpecialAwesome а также FizBuzz καιΚάτιΑκόμα" будет преобразован в "super_special_awesome а также fizz_buzz και_κάτι_ακόμα".
mb_strtolower( preg_replace_callback( '/(?<!\b|_)\p{Lu}/u', function ($a) { return "_$a[0]"; }, 'SuperSpecialAwesome' ) );
Laravel 5.6 предоставляет очень простой способ сделать это:
/** * 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', ''.$delimiter, $value)); } return $value; }
что он делает: если он видит, что в данной строке есть хотя бы одна заглавная буква, он использует позитивный просмотр вперед для поиска любого символа (
.
), за которым следует заглавная буква ((?=[A-Z])
). Затем он заменяет найденный символ его значением, за которым следует разделитель_
.
вот что я использую для декамелизации метода:
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"
Если вы используете Laravel framework, вы можете использовать только snake_case () метод.
легко использовать классы фильтров 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; } }
- - - - - 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
худший ответ здесь был так близок к тому, чтобы быть лучшим(используйте фреймворк). Нет, не надо, просто взгляните на исходный код. видя, что хорошо налаженная структура использует будет гораздо более надежный подход (испытанный и проверенный). Zend framework имеет некоторые фильтры слов, которые соответствуют вашим потребностям. источник.
вот несколько методов, которые я адаптировал из источника.
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 . '', $separator . '']; } else { $pattern = ['#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#']; $replacement = ['' . $separator . '', $separator . '']; } return preg_replace($pattern, $replacement, $value); } function CamelCaseToUnderscore($value){ return CamelCaseToSeparator($value,'_'); } function CamelCaseToDash($value){ return CamelCaseToSeparator($value,'-'); } $string = CamelCaseToUnderscore("CamelCase");
библиотека 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'
Yii2 имеют другую функцию, чтобы сделать слово snake_case из CamelCase.
/** * 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)); }
если бы вы могли начать с:
$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