Si tuviera:
$string = "PascalCase";
Necesito
"pascal_case"
¿PHP ofrece una función para este propósito?
Si tuviera:
$string = "PascalCase";
Necesito
"pascal_case"
¿PHP ofrece una función para este propósito?
Respuestas:
Pruébate esto para ver 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 siguientes reglas:
Una solución más corta: similar a la del editor con una expresión regular simplificada y solucionando el problema de "guión bajo al final":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Demostración de PHP | Demostración de expresiones regulares
Tenga en cuenta que los casos como SimpleXML
se convertirán para simple_x_m_l
usar la solución anterior. Eso también puede considerarse un uso incorrecto de la notación de mayúsculas y minúsculas (lo correcto sería SimpleXml
) en lugar de un error del algoritmo, ya que tales casos son siempre ambiguos, incluso al agrupar caracteres en mayúscula en una cadena ( simple_xml
), dicho algoritmo siempre fallará en otros casos de borde. me gusta XMLHTMLConverter
o palabras de una letra cerca de abreviaturas, etc. Si no le importan los casos extremos (bastante raros) y desea manejarlos SimpleXML
correctamente, puede usar una solución un poco más compleja:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Una solución concisa que puede manejar algunos casos de uso complicados:
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 de Ruby's String#camelize
y 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);
}
Un truco que las soluciones anteriores pueden haber pasado por alto es el modificador 'e' que hace preg_replace
que se evalúe la cadena de reemplazo como código PHP.
e
bandera para preg_replace
está en desuso en PHP 5.5.
^|
o strlen
.
El componente de serializador de Symfony tiene un CamelCaseToSnakeCaseNameConverter que tiene dos métodos normalize()
y denormalize()
. Estos se pueden utilizar de la siguiente manera:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
$nameConverter->normalize('CamelCase')
salidas _camel_case
en la versión 3.2 actual del componente de serializador de Symfony.
La mayoría de las soluciones aquí se sienten torpes. Esto es lo que 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 (evita que la salida convertida 'CamelCASE' comience con un guión bajo)[A-Z]
encuentra letras mayúsculas+
tratará cada mayúscula consecutiva como una palabra (evita que 'CamelCASE' se convierta en camel_C_A_S_E)ThoseSPECCases
-> en those_spec_cases
lugar dethose_speccases
strtolower([…])
convierte la salida en minúsculaslcfirst
función a $ camelCase
ucfirst()
llamada. USADollarSymbol
se convierte en u_sa_dollar_symbol
demostración No recomiendo esta solución porque tiene que hacer dos pasadas a través de la cadena de entrada con expresiones regulares, un signo de un patrón sin refinar.
php no ofrece una función incorporada para este afaik, pero esto es lo que 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 a la función, por lo que puede llamarlo así
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
y la /u
opción activada preg_replace
.
Debe ejecutar una expresión regular que coincida con todas las letras mayúsculas, excepto si está al principio, y reemplazarla con un subrayado más esa letra. Una solución utf-8 es esta:
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 no está seguro de qué caso es su cadena, es mejor verificarla primero, porque este código asume que la entrada es en camelCase
lugar de underscore_Case
odash-Case
, por lo que si las últimas tienen letras mayúsculas, les agregará guiones bajos.
La respuesta aceptada de cletus es demasiado complicada en mi humilde opinión y funciona solo con caracteres latinos. Me parece una solución realmente mala y me pregunto por qué fue aceptada. Convertir TEST123String
en test123_string
no es necesariamente un requisito válido. Preferí mantenerlo simple y separado ABCccc
en a_b_cccc
lugar de ab_cccc
porque no pierde información de esta manera y la conversión hacia atrás dará exactamente la misma cadena con la que comenzamos. Incluso si desea hacerlo de la otra manera, es relativamente fácil escribir una expresión regular con una mirada atrás positiva (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
o dos expresiones regulares sin mirar atrás si no es un experto en expresiones regulares. No hay necesidad de dividirlo en subcadenas sin mencionar decidir entre strtolower
y lcfirst
dónde usarlo strtolower
estaría completamente bien.
Si está buscando una versión de PHP 5.4 y una respuesta posterior, 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 nada sofisticado, pero es simple y rápido como el infierno:
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
++$i
en lugar de $i++
lo haría un poco más rápido también;)
"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, '_');
}
this-kind-of-output
Se puede encontrar una versión que no usa expresiones regulares en la fuente de 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);
}
Así que aquí hay una sola línea:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
g
modificador a esta expresión regular.
g
él y funciona bien para mí.
g
. Pero no recuerdo la frase con la que probé.
danielstjules / Stringy proporciona un método para convertir cadenas de camelcase a snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 proporciona una forma 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;
}
Qué hace: si ve que hay al menos una letra mayúscula en la cadena dada, usa una búsqueda anticipada positiva para buscar cualquier carácter ( .
) seguido de una letra mayúscula ( (?=[A-Z])
). Luego reemplaza el carácter encontrado con su valor seguido por el separador _
.
El puerto directo desde rieles (menos su manejo especial para :: o siglas) 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, '-', '_'));
}
Conociendo PHP, esto será más rápido que el análisis manual que está sucediendo en otras respuestas dadas aquí. La desventaja es que no puedes elegir qué usar como separador entre palabras, pero eso no era parte de la pregunta.
También verifique el código fuente de rieles relevante
Tenga en cuenta que está diseñado para su uso con identificadores ASCII. Si necesita hacer esto con caracteres fuera del rango ASCII, use el modificador '/ u' para preg_match
y use mb_strtolower
.
Aquí está mi contribución a una pregunta de seis años con Dios sabe cuántas respuestas ...
Convertirá todas las palabras en la cadena proporcionada que están en camelcase a snakecase. Por ejemplo, "SuperSpecialAwesome y también FizBuzz καιΚάτιΑκόμα" se convertirán 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 tiene la función diferente 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));
}
Solución corta:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Tuve un problema similar, pero no pude encontrar ninguna respuesta que satisfaga cómo convertir CamelCase a snake_case, evitando al mismo tiempo guiones bajos duplicados o redundantes _
para nombres con guiones bajos o abreviaturas en mayúsculas.
El problema es el siguiente:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
La solución que escribí es una simple llamada de dos funciones, minúsculas y buscar y reemplazar por letras minúsculas y mayúsculas consecutivas:
strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
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);
}
$name{$k}
(o $name[$k]
), lo que alargaría su código, pero evita la gran sobrecarga de convertirlo hacia y desde una matriz.
La peor respuesta aquí estuvo muy cerca de ser la mejor (use un marco). NO NO, simplemente eche un vistazo al código fuente. ver lo que utiliza un marco bien establecido sería un enfoque mucho más confiable (probado y comprobado). El marco Zend tiene algunos filtros de palabras que se adaptan a sus necesidades. Fuente .
aquí hay un par de métodos que adapté 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");
Hay una biblioteca que proporciona esta funcionalidad:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Si usa el framework Laravel, puede usar solo el método snake_case () .
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 des-camelizar sin usar 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 haría eso en 2019?
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
Y cuándo se lanzará PHP 7.4:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
Es fácil usar las clases de filtro de los filtros Zend Word :
<?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;
}
}
----- subrayadoToCamelCase -----
simple_test >>> SimpleTest
fácil >>> Fácil
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
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 biblioteca TurboCommons de código abierto contiene un método formatCase () de propósito general dentro de la clase StringUtils, que le permite convertir una cadena a muchos formatos de casos comunes, como CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case y muchos más.
https://github.com/edertone/TurboCommons
Para usarlo, importe 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'
$str = 'FooBarBaz';
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
SI pudieras comenzar con:
$string = 'Camel_Case'; // underscore or any other separator...
Entonces podrías convertir a cualquier caso solo 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