Cómo convertir PascalCase a pascal_case?
-
22-09-2019 - |
Pregunta
Si tuviera:
$string = "PascalCase";
Necesito
"pascal_case"
¿El PHP ofrece una función para este propósito?
Solución
Pruebe esto en el tamaño:
$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);
}
Salida:
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
Esto implementa las reglas siguientes:
- Una secuencia comenzando con una letra minúscula debe ser seguida por letras minúsculas y dígitos;
- Una secuencia comenzando con una letra mayúscula puede ser seguido por cualquiera de:
- una o letras y dígitos más mayúsculas (seguido por o bien el final de la cadena o una letra mayúscula seguida por una letra minúscula o dígito es decir, el inicio de la siguiente secuencia); o
- una o más letras o dígitos minúsculas.
Otros consejos
Una solución más corto: Al igual que en el del editor una con una expresión regular simplificada y se fija el "arrastre-subrayado" problema:
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
PHP demostración | Regex demostración
Nota que casos como SimpleXML
se convertirán a simple_x_m_l
usando la solución anterior. Eso también puede ser considerado como un mal uso de la caja de camello notación (correcta sería SimpleXml
) en lugar de un error del algoritmo, ya que tales casos son siempre ambiguos - incluso mediante la agrupación de mayúsculas caracteres de una cadena (simple_xml
) como algoritmo siempre fallará en otra casos extremos como XMLHTMLConverter
o palabras de una letra cerca de abreviaturas, etc. Si no se cuenta sobre el lugar (raros) casos extremos y desea correctamente a SimpleXML
mango, se puede utilizar una solución poco más complejo:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
solución concisa A y puede manejar algunos casos de uso complicado:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
Puede manejar todos estos casos:
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
Puede probar esta función aquí: http://syframework.alwaysdata.net/decamelize
portado desde String#camelize
y String#decamelize
de Ruby.
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);
}
Un truco las soluciones anteriores pueden haber perdido es la 'e' modificador que causa preg_replace
para evaluar la cadena de reemplazo como código PHP.
El Symfony Serializer Componente tiene un CamelCaseToSnakeCaseNameConverter que tiene dos métodos normalize()
y denormalize()
. Estos pueden ser utilizados como sigue:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
La mayoría de las soluciones que aquí se sienten de mano dura. Esto es lo que yo uso:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_$1", "_$1_$2"],
lcfirst($camelCase)
)
);
"camelCase" se convierte en "camel_case"
-
lcfirst($camelCase)
bajará el primer carácter (salida convertida evita 'camelCase' para comenzar con un guión bajo) -
[A-Z]
encuentra mayúsculas -
+
va a tratar cada mayúsculas consecutivo como una palabra (evita 'camelCase' para ser convertido en camel_C_A_S_E) - En segundo patrón y la sustitución son para
ThoseSPECCases
->those_spec_cases
en lugar dethose_speccases
-
strtolower([…])
convierte la salida a minúsculas
php no ofrece una función integrada para este yo sepa, pero aquí es lo que yo uso
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
return strtolower($camel);
}
el divisor se puede especificar en la llamada de función, por lo que se le puede llamar como tal
$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', '_$0', 'AaaaBbbbCcccDdddÁáááŐőőő');
$lower = mb_strtolower($separated, 'utf-8');
echo $lower; //aaaa_bbbb_cccc_dddd_áááá_őőőő
Si usted está buscando una versión de PHP 5.4 y posterior respuesta aquí está el código:
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
);
}
No es lujoso pero simple y rápido como el demonio:
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
"CamelCase" a "camel_case":
function camelToSnake($camel)
{
$snake = preg_replace('/[A-Z]/', '_$0', $camel);
$snake = strtolower($snake);
$snake = ltrim($snake, '_');
return $snake;
}
o
function camelToSnake($camel)
{
$snake = preg_replace_callback('/[A-Z]/', function ($match){
return '_' . strtolower($match[0]);
}, $camel);
return ltrim($snake, '_');
}
Una versión que no utiliza expresiones regulares se puede encontrar en el href="http://alchitect.com" rel="nofollow noreferrer"> Alchitect fuente 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);
}
Así que aquí hay una sola línea:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
danielstjules / viscosa provieds un método para convertir la cadena de CamelCase para snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
laravel 5.6 proporciona una manera muy sencilla de hacer esto:
/**
* 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;
}
Lo que hace: si ve que hay al menos una letra mayúscula en la cadena dada, se utiliza un búsqueda positiva hacia delante para buscar cualquier carácter (.
) seguido de una letra mayúscula ((?=[A-Z])
). A continuación, reemplaza el carácter encontrado con su valor seguido por el _
separactor.
El puerto directo de carriles (menos su manejo especial para :: o acrónimos) sería
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, '-', '_'));
}
El saber PHP, esto va a ser más rápido que el análisis manual que está sucediendo en otras respuestas que se dan aquí. La desventaja es que no dan a elegir lo que a su uso como un separador entre las palabras, pero eso no era parte de la pregunta.
También compruebe la fuente relevante rieles código
Tenga en cuenta que esto es para uso con identificadores ASCII. Si necesita hacer esto con caracteres fuera del rango ASCII, utilice el '/ T' modificador para uso preg_match
and mb_strtolower
.
Esta es mi contribución a una pregunta de seis años de edad, con Dios sabe cuántas respuestas ...
Se convertirá todas las palabras de la cadena, siempre que se encuentren en CamelCase para snakecase. Por ejemplo "SuperSpecialAwesome y también FizBuzz καιΚάτιΑκόμα" se convertirá en "super_special_awesome y también fizz_buzz και_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 tener la diversa función para hacer la palabra snake_case de 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));
}
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);
}
Hay una biblioteca proporcionar esta funcionalidad:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Si utiliza marco laravel, puede utilizar simplemente snake_case () método.
$str = 'FooBarBaz';
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
Esta es una de las formas más cortas:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
¿Cómo de-camelize sin utilizar expresiones regulares:
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;
}
Una edición:
¿Cómo iba a hacer eso en 2019:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
Y cuando PHP 7.4 será liberado:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
solución corta:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Es fácil utilizando las clases de filtros del Zend Palabra filtros :
<?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
fácil >>> Fácil
>>> html HTML
simple_xml >>> SimpleXML
pdf_load >>> PdfLoad
start_middle_last >>> StartMiddleLast
una_cadena >>> AString
some4_numbers234 >>> Some4Numbers234
test123_string >>> Test123String
----- ----- camelCaseToUnderscore
SimpleTest >>> simple_test
>>> fácil fácil
HTML >>> html
simplexml >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLELast >>> start_middle_last
AString >>> una_cadena
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
La peor respuesta aquí era tan cerca de ser el mejor (utilizar un marco). NO No, sólo echar un vistazo al código fuente. viendo lo que es un bien establecidos usos marco sería un enfoque mucho más fiable (probadas). El marco de Zend tiene algunos filtros de palabras que se ajustan a sus necesidades. Fuente .
aquí es un par de métodos que Adaptado de la fuente.
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");
La biblioteca TurboCommons código abierto contiene un método formatCase propósito general () dentro de la clase StringUtils, que permite convertir una cadena a una gran cantidad de formatos de casos comunes, como CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Título del caso, y muchos más.
https://github.com/edertone/TurboCommons
Para usarlo, importar el archivo Phar a su proyecto y:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);
// will output 'camel_Case'
He tenido un problema similar, pero no pude encontrar ninguna respuesta que satisface la forma de convertir CamelCase para snake_case, evitando al mismo tiempo guiones duplicados o redundantes _
de nombres con guiones bajos, o todas las abreviaturas caps.
Th problema es como sigue:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
La solución que escribí es una sencilla dos funciones llaman, minúsculas y búsqueda y reemplazo para las letras minúsculas consecutivas-mayúsculas:
strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
Si usted podría comenzar con:
$string = 'Camel_Case'; // underscore or any other separator...
A continuación, se podría convertir en cualquiera de los casos simplemente con:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
o cualquier otro caso:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case