Se avessi:
$string = "PascalCase";
ho bisogno
"pascal_case"
PHP offre una funzione per questo scopo?
Se avessi:
$string = "PascalCase";
ho bisogno
"pascal_case"
PHP offre una funzione per questo scopo?
Risposte:
Prova questo per le dimensioni:
$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);
}
Produzione:
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
Questo implementa le seguenti regole:
Una soluzione più breve: simile a quella dell'editor con un'espressione regolare semplificata e che risolve il problema "trailing-underscore":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Nota che casi come SimpleXML
verranno convertiti simple_x_m_l
utilizzando la soluzione di cui sopra. Questo può anche essere considerato un uso errato della notazione delle maiuscole (sarebbe corretto SimpleXml
) piuttosto che un bug dell'algoritmo poiché tali casi sono sempre ambigui - anche raggruppando caratteri maiuscoli in una stringa ( simple_xml
) tale algoritmo fallirà sempre in altri casi limite XMLHTMLConverter
parole simili o di una lettera accanto alle abbreviazioni, ecc. Se non ti interessano i casi limite (piuttosto rari) e desideri gestirli SimpleXML
correttamente, puoi utilizzare una soluzione un po '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 d'uso complicati:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
Può 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
Puoi testare questa funzione qui: http://syframework.alwaysdata.net/decamelize
Portato da Ruby String#camelize
e 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 trucco che le soluzioni precedenti potrebbero aver perso è il modificatore "e" che fa preg_replace
valutare la stringa di sostituzione come codice PHP.
e
flag per preg_replace
è stato deprecato in PHP 5.5.
^|
o strlen
.
Il componente Serializer di Symfony ha un CamelCaseToSnakeCaseNameConverter che ha due metodi normalize()
e denormalize()
. Questi possono essere usati come segue:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
$nameConverter->normalize('CamelCase')
output _camel_case
nella versione corrente 3.2 del componente Serializer di Symfony.
La maggior parte delle soluzioni qui sembra pesante. Ecco cosa utilizzo:
$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 che l'output convertito di 'CamelCASE' inizi con un trattino basso)[A-Z]
trova le lettere maiuscole+
tratterà ogni maiuscolo consecutivo come una parola (evita che "CamelCASE" venga convertito in camel_C_A_S_E)ThoseSPECCases
-> those_spec_cases
invece dithose_speccases
strtolower([…])
trasforma l'output in minuscololcfirst
funzione a $ camelCase
ucfirst()
chiamata. USADollarSymbol
diventa u_sa_dollar_symbol
Demo Non consiglio questa soluzione perché deve fare due passaggi attraverso la stringa di input con regex - segno di un pattern non raffinato.
php non offre una funzione integrata per questo afaik, ma ecco cosa 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, quindi puoi chiamarlo in questo modo
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
e l' /u
opzione su preg_replace
.
È necessario eseguire un'espressione regolare attraverso di essa che corrisponda a ogni lettera maiuscola tranne se è all'inizio e sostituirla con un trattino basso più quella lettera. Una soluzione utf-8 è questa:
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 non sei sicuro di quale sia il caso della tua stringa, è meglio controllarlo prima, perché questo codice presuppone che l'input sia camelCase
invece di underscore_Case
o dash-Case
, quindi se questi ultimi hanno lettere maiuscole, aggiungerà caratteri di sottolineatura.
La risposta accettata da cletus è troppo complicata imho e funziona solo con caratteri latini. La trovo davvero una pessima soluzione e mi chiedo perché sia stata accettata. La conversione TEST123String
in test123_string
non è necessariamente un requisito valido. L'ho tenuto piuttosto semplice e separato ABCccc
in a_b_cccc
invece di ab_cccc
perché non perde le informazioni in questo modo e la conversione all'indietro darà la stessa identica stringa con cui abbiamo iniziato. Anche se vuoi farlo in un altro modo, è relativamente facile scrivere una regex con lookbehind positivo (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
o due regex senza lookbehind se non sei un esperto di regex. Non è necessario dividerlo in sottostringhe per non parlare di decidere tra strtolower
e lcfirst
dove usarlo strtolower
andrebbe benissimo.
Se stai cercando una versione PHP 5.4 e una risposta successiva, ecco 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
);
}
Per niente elegante ma semplice e veloce da morire:
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
invece di $i++
renderlo anche un po 'più veloce;)
Da "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
Una versione che non usa regex può essere trovata nella fonte 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);
}
Quindi ecco una battuta:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
g
modificatore a questa regex.
g
e funziona bene per me.
g
. Ma non ricordo la frase con cui ho provato.
danielstjules / Stringy ha fornito un metodo per convertire le stringhe da camelcase a snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 fornisce un modo molto semplice per farlo:
/**
* 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 c'è almeno una lettera maiuscola nella stringa data, usa un lookahead positivo per cercare qualsiasi carattere ( .
) seguito da una lettera maiuscola ( (?=[A-Z])
). Quindi sostituisce il carattere trovato con il suo valore seguito dal separatore _
.
La porta diretta da rails (meno la loro gestione 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, '-', '_'));
}
Conoscendo PHP, questo sarà più veloce dell'analisi manuale che sta accadendo in altre risposte fornite qui. Lo svantaggio è che non puoi scegliere cosa usare come separatore tra le parole, ma questo non faceva parte della domanda.
Controlla anche il codice sorgente delle guide rilevanti
Notare che questo è inteso per l'uso con identificatori ASCII. Se è necessario eseguire questa operazione con caratteri al di fuori dell'intervallo ASCII, utilizzare il modificatore "/ u" per preg_match
e utilizzare mb_strtolower
.
Ecco il mio contributo a una domanda di sei anni con dio sa quante risposte ...
Convertirà tutte le parole nella stringa fornita che si trovano in camelcase in snakecase. Ad esempio "SuperSpecialAwesome e anche FizBuzz καιΚάτιΑκόμα" verranno 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 ha la diversa funzione di creare 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));
}
Soluzione breve:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Ho avuto un problema simile ma non sono riuscito a trovare alcuna risposta che soddisfi come convertire CamelCase in snake_case, evitando caratteri di sottolineatura duplicati o ridondanti _
per i nomi con trattini bassi o abbreviazioni tutte maiuscole.
Il problema è il seguente:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
La soluzione che ho scritto è una semplice chiamata a due funzioni, minuscolo e cerca e sostituisci per lettere minuscole-maiuscole consecutive:
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]
), il che renderebbe il tuo codice più lungo, ma evita il grande sovraccarico di convertirlo in e da un array.
La risposta peggiore qui era così vicina all'essere la migliore (usa un framework). NO NON FARE, basta dare un'occhiata al codice sorgente. vedere cosa utilizza un framework ben consolidato sarebbe un approccio molto più affidabile (provato e testato). Il framework Zend ha alcuni filtri di parole che si adattano alle tue esigenze. Fonte .
ecco un paio di metodi che ho 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");
C'è una libreria che fornisce questa funzionalità:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Se usi il framework Laravel, puoi usare solo il metodo snake_case () .
Questo è uno dei modi più brevi:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Come de-camelize senza usare regex:
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 lo farei nel 2019:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
E quando verrà rilasciato PHP 7.4:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
È facile usare le classi Filter dei filtri 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;
}
}
----- ----- 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 libreria TurboCommons open source contiene un metodo formatCase () generico all'interno della classe StringUtils, che consente di convertire una stringa in molti formati di maiuscole e minuscole comuni, come CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case e molti altri.
https://github.com/edertone/TurboCommons
Per usarlo, importa il file phar nel tuo progetto e:
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
SE potresti iniziare con:
$string = 'Camel_Case'; // underscore or any other separator...
Quindi puoi convertire in entrambi i casi solo con:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
O qualsiasi altro caso:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case