Come convertire PascalCase a pascal_case?
-
22-09-2019 - |
Domanda
Se avessi:
$string = "PascalCase";
Ho bisogno
"pascal_case"
Il PHP offrono una funzione per questo scopo?
Soluzione
Prova questo per il formato:
$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);
}
Output:
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
Questa implementa le seguenti regole:
- Una sequenza inizia con una lettera minuscola deve essere seguita da lettere minuscole e cifre;
- Una sequenza che inizia con una lettera maiuscola può essere seguito da uno:
- una o più lettere maiuscole e cifre (seguiti dalle estremità della stringa o una lettera maiuscola seguita da una lettera minuscola o cifre, cioè l'inizio della successiva sequenza); o
- una o più lettere minuscole o cifre.
Altri suggerimenti
Una soluzione più corta: Simile al dell'editor uno con un'espressione regolare semplificato e risolvere il problema "trailing-underscore":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Si noti che casi come SimpleXML
saranno convertiti simple_x_m_l
utilizzando la soluzione di cui sopra. Che può anche essere considerato un uso sbagliato di caso cammello notazione (corretta sarebbe SimpleXml
), piuttosto che un bug dell'algoritmo in quanto tali casi sono sempre ambigui - anche dal raggruppamento di caratteri maiuscoli a una stringa (simple_xml
) tale algoritmo sarà sempre fallire in altri casi limite come XMLHTMLConverter
o uno parolacce vicino abbreviazioni, ecc Se non si mente circa i casi (piuttosto rara) bordo e desidera gestire correttamente SimpleXML
, è possibile utilizzare un po 'di soluzione più complessa:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Una soluzione concisa e in grado di gestire alcuni casi di utilizzo ingannevole:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
In grado di gestire tutti questi casi:
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
È possibile provare questa funzione qui: http://syframework.alwaysdata.net/decamelize
porting da String#camelize
e String#decamelize
di 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 trucco le soluzioni di cui sopra possono avere perso è il modificatore 'e' che provoca preg_replace
di valutare la stringa di sostituzione come codice PHP.
Il Symfony Serializer Componente ha una CamelCaseToSnakeCaseNameConverter che ha due metodi normalize()
e denormalize()
. Questi possono essere utilizzati come segue:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
La maggior parte delle soluzioni qui si sentono mano pesante. Ecco quello che io uso:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_$1", "_$1_$2"],
lcfirst($camelCase)
)
);
"CamelCase" viene convertito in "camel_case"
-
lcfirst($camelCase)
abbasserà il primo carattere (evita 'camelCase' convertito uscita per iniziare con un trattino) -
[A-Z]
ritrova lettere maiuscole -
+
tratterà ogni maiuscolo consecutivo come una parola ( 'evita camelCase' da convertire in camel_C_A_S_E) - Secondo modello e la sostituzione sono per
ThoseSPECCases
->those_spec_cases
invece dithose_speccases
-
strtolower([…])
trasforma l'uscita in minuscolo
php non offre una costruito in funzione di questo afaik, ma qui è quello che io uso
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
return strtolower($camel);
}
lo splitter può essere specificato nella chiamata di funzione, in modo da poter chiamare in questo modo
$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_áááá_őőőő
Se siete alla ricerca di una versione di PHP 5.4 e successive risposta qui è il codice:
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
);
}
Non lussuoso ma semplice e veloce come l'inferno:
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 versione che non utilizza regex può essere trovato nel href="http://alchitect.com" rel="nofollow noreferrer"> Alchitect fonte 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);
}
Quindi, ecco una battuta:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
danielstjules / filante provieds un metodo per convertire la stringa da CamelCase a snake case.
s('TestUCase')->underscored(); // 'test_u_case'
laravel 5.6 fornisce un modo molto semplice di fare questo:
/**
* 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;
}
Cosa fa: se vede che ci sia almeno una lettera maiuscola nella stringa data, utilizza un positivo lookahead per la ricerca di qualsiasi carattere (.
) seguito da una lettera maiuscola ((?=[A-Z])
). Esso sostituisce quindi il carattere trovato con il suo valore seguito dal _
separactor.
Il porto diretta da rotaie (meno il loro trattamento speciale per :: o acronimi) sarebbe
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, '-', '_'));
}
Conoscere PHP, questo sarà più veloce rispetto al parsing manuale che sta accadendo in altre risposte qui riportati. Lo svantaggio è che non si arriva a scegliere cosa usare come separatore tra le parole, ma che non faceva parte della questione.
Controllare anche la rilevante fonte rotaie codice
Si noti che questo è destinato all'uso con identificatori ASCII. Se avete bisogno di fare questo con i personaggi al di fuori del range ASCII, utilizzare il modificatore '/ u' per l'uso preg_match
and mb_strtolower
.
Ecco il mio contributo a una domanda di sei anni con Dio sa quante risposte ...
Sarà convertire tutte le parole nella stringa a condizione che sono in CamelCase a snake case. Ad esempio, "SuperSpecialAwesome e anche FizBuzz καιΚάτιΑκόμα" saranno convertiti in "super_special_awesome e anche fizz_buzz και_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 hanno la diversa funzione di rendere la parola snake_case da 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);
}
Se si utilizza quadro laravel, è possibile utilizzare solo snake_case () metodo.
$str = 'FooBarBaz';
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
Questo è uno dei modi più brevi:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Come de-camelize senza l'utilizzo di espressioni regolari:
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 modifica:
Come dovrei farlo nel 2019:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
E quando il PHP 7.4 sarà rilasciato:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
soluzione breve:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
E 'facile utilizzando le classi di filtro della Zend Word filtri :
<?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
>>> facile facile
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
>>> facile facile
HTML >>> html
SimpleXML >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLELast >>> start_middle_last
astring >>> a_string
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
La risposta peggiore qui è stato così vicino ad essere il migliore (utilizzare un framework). NO NON, basta dare un'occhiata al codice sorgente. vedendo ciò che un uso quadro ben consolidata sarebbe un approccio molto più affidabile (provati e testati). Il framework Zend ha alcuni filtri parola che si adattano alle vostre esigenze. Source.
ecco un paio di metodi mi sono adattato dalla fonte.
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 open source contiene un metodo generale scopo formatCase () all'interno della classe StringUtils, che permette di convertire una stringa in un sacco di formati più comuni casi, come CamelCase, UpperCamelCase, LowerCamelCase, snake_case, caso di titolo, e molti altri.
https://github.com/edertone/TurboCommons
Per utilizzarlo, importare il file phar al progetto e:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);
// will output 'camel_Case'
Ho avuto un problema simile, ma non ho trovato alcuna risposta che soddisfi come convertire CamelCase a snake_case, evitando duplicati o ridondanti sottolineature _
per i nomi con sottolineature, o tutti caps abbreviazioni.
Th problema è come segue:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
La soluzione che ho scritto è un semplice due funzioni di chiamata, minuscole e di ricerca e sostituzione per le lettere minuscole-maiuscole consecutive:
strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));
Se si potrebbe iniziare con:
$string = 'Camel_Case'; // underscore or any other separator...
Poi si potrebbe convertire in entrambi i casi solo con:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
O tutti gli altri casi:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case