Hätte ich:
$string = "PascalCase";
Ich brauche
"pascal_case"
Bietet PHP eine Funktion für diesen Zweck?
Hätte ich:
$string = "PascalCase";
Ich brauche
"pascal_case"
Bietet PHP eine Funktion für diesen Zweck?
Antworten:
Probieren Sie dies für die Größe an:
$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);
}
Ausgabe:
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
Dies implementiert die folgenden Regeln:
Eine kürzere Lösung: Ähnlich wie beim Editor mit einem vereinfachten regulären Ausdruck und der Behebung des Problems des "nachgestellten Unterstrichs":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Beachten Sie, dass Fälle wie SimpleXML
die simple_x_m_l
Verwendung der obigen Lösung konvertiert werden. Dies kann auch als falsche Verwendung der Kamelschreibweise (richtig wäre SimpleXml
) und nicht als Fehler des Algorithmus angesehen werden, da solche Fälle immer mehrdeutig sind - selbst wenn Gruppen in Großbuchstaben zu einer Zeichenfolge gruppiert werden ( simple_xml
), schlägt ein solcher Algorithmus in anderen Randfällen immer fehl Like- XMLHTMLConverter
oder Ein-Buchstaben-Wörter in der Nähe von Abkürzungen usw. Wenn Sie sich nicht für die (eher seltenen) Randfälle interessieren und SimpleXML
richtig damit umgehen möchten, können Sie eine etwas komplexere Lösung verwenden:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Eine prägnante Lösung, die einige knifflige Anwendungsfälle bewältigen kann:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
Kann alle diese Fälle behandeln:
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
Sie können diese Funktion hier testen: http://syframework.alwaysdata.net/decamelize
Portiert von Ruby's String#camelize
und 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);
}
Ein Trick, den die oben genannten Lösungen möglicherweise übersehen haben, ist der Modifikator 'e', der dazu führt preg_replace
, dass die Ersatzzeichenfolge als PHP-Code ausgewertet wird.
e
Flag für preg_replace
wird in PHP 5.5 veraltet.
^|
oder nicht strlen
.
Die Symfony Serializer-Komponente verfügt über einen CamelCaseToSnakeCaseNameConverter mit zwei Methoden normalize()
und denormalize()
. Diese können wie folgt verwendet werden:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
$nameConverter->normalize('CamelCase')
Ausgaben _camel_case
in der aktuellen Version 3.2 der Symfony Serializer-Komponente.
Die meisten Lösungen hier fühlen sich schwerfällig an. Folgendes verwende ich:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_$1", "_$1_$2"],
lcfirst($camelCase)
)
);
"CamelCASE" wird in "camel_case" konvertiert
lcfirst($camelCase)
verringert das erste Zeichen (vermeidet die konvertierte Ausgabe von 'CamelCASE', um mit einem Unterstrich zu beginnen)[A-Z]
findet Großbuchstaben+
behandelt jeden aufeinanderfolgenden Großbuchstaben als Wort (verhindert, dass 'CamelCASE' in camel_C_A_S_E konvertiert wird)ThoseSPECCases
-> those_spec_cases
stattthose_speccases
strtolower([…])
Schaltet die Ausgabe in Kleinbuchstaben umlcfirst
Funktion $ Camelcase
ucfirst()
Aufrufs unerwartet aufgeteilt . USADollarSymbol
wird u_sa_dollar_symbol
Demo Ich empfehle diese Lösung nicht, da sie zwei Durchgänge mit Regex durch die Eingabezeichenfolge machen muss - ein Zeichen für ein nicht verfeinertes Muster.
PHP bietet keine eingebaute Funktion für diesen Afaik, aber hier ist, was ich benutze
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
return strtolower($camel);
}
Der Splitter kann im Funktionsaufruf angegeben werden, so dass Sie ihn so aufrufen können
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
und die /u
Option aktivieren preg_replace
.
Sie müssen einen regulären Ausdruck durchlaufen, der mit jedem Großbuchstaben übereinstimmt, außer wenn er am Anfang steht, und ihn durch einen Unterstrich plus diesen Buchstaben ersetzen. Eine utf-8-Lösung ist folgende:
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_áááá_őőőő
Wenn Sie sich nicht sicher sind, in welchem Fall sich Ihre Zeichenfolge befindet, überprüfen Sie sie besser zuerst, da dieser Code davon ausgeht, dass die Eingabe camelCase
anstelle von underscore_Case
oder erfolgtdash-Case
erfolgt. Wenn die letzteren also Großbuchstaben enthalten, werden ihnen Unterstriche hinzugefügt.
Die akzeptierte Antwort von Cletus ist imho viel zu kompliziert und funktioniert nur mit lateinischen Zeichen. Ich finde es eine wirklich schlechte Lösung und frage mich, warum es überhaupt akzeptiert wurde. Die Konvertierung TEST123String
in test123_string
ist nicht unbedingt eine gültige Voraussetzung. Ich eher hielt es einfach und getrennt ABCccc
in a_b_cccc
statt , ab_cccc
weil es nicht verlieren Informationen auf diese Weise und die Rückkonvertierung wird genau die gleiche Zeichenfolge wir begannen mit geben. Selbst wenn Sie es anders machen möchten, ist es relativ einfach, eine Regex mit positivem Lookbehind (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
oder zwei Regexes ohne Lookbehind zu schreiben, wenn Sie kein Regex-Experte sind. Es besteht keine Notwendigkeit, es in Teilzeichenfolgen aufzuteilen, ganz zu schweigen von der Entscheidung, zwischen strtolower
und lcfirst
wo die Verwendung nur strtolower
völlig in Ordnung wäre.
Wenn Sie nach einer PHP 5.4-Version suchen und später antworten, ist hier der Code:
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
);
}
Gar nichts Besonderes, aber einfach und schnell wie die Hölle:
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
anstatt $i++
würde es auch ein bisschen schneller machen;)
"CamelCase" bis "camel_case":
function camelToSnake($camel)
{
$snake = preg_replace('/[A-Z]/', '_$0', $camel);
$snake = strtolower($snake);
$snake = ltrim($snake, '_');
return $snake;
}
oder:
function camelToSnake($camel)
{
$snake = preg_replace_callback('/[A-Z]/', function ($match){
return '_' . strtolower($match[0]);
}, $camel);
return ltrim($snake, '_');
}
this-kind-of-output
Eine Version, die keinen regulären Ausdruck verwendet, finden Sie in der Alchitect- Quelle:
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);
}
Also hier ist ein Einzeiler:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
g
, diesem regulären Ausdruck einen Modifikator hinzuzufügen .
g
und es funktioniert gut für mich.
g
. Aber ich kann mich nicht an den Satz erinnern, mit dem ich getestet habe.
danielstjules / Stringy hat eine Methode zum Konvertieren von Strings von Camelcase in Snakecase bereitgestellt.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 bietet eine sehr einfache Möglichkeit, dies zu tun:
/**
* 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;
}
Was es tut: Wenn es sieht, dass die angegebene Zeichenfolge mindestens einen Großbuchstaben enthält, verwendet es einen positiven Lookahead , um nach einem Zeichen ( .
) zu suchen, gefolgt von einem Großbuchstaben ( (?=[A-Z])
). Anschließend wird das gefundene Zeichen durch seinen Wert ersetzt, gefolgt vom Trennzeichen _
.
Der direkte Port von Schienen (abzüglich ihrer speziellen Behandlung für :: oder Akronyme) wäre
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, '-', '_'));
}
Wenn Sie PHP kennen, ist dies schneller als das manuelle Parsen, das in anderen hier gegebenen Antworten durchgeführt wird. Der Nachteil ist, dass Sie nicht auswählen können, was als Trennzeichen zwischen Wörtern verwendet werden soll, aber das war nicht Teil der Frage.
Überprüfen Sie auch den entsprechenden Rails-Quellcode
Beachten Sie, dass dies für die Verwendung mit ASCII-Kennungen vorgesehen ist. Wenn Sie dies mit Zeichen außerhalb des ASCII-Bereichs tun müssen, verwenden Sie den Modifikator '/ u' für preg_match
und verwenden Sie mb_strtolower
.
Hier ist mein Beitrag zu einer sechs Jahre alten Frage mit Gott weiß, wie viele Antworten ...
Es werden alle Wörter in der bereitgestellten Zeichenfolge, die sich in camelcase befinden, in snakecase konvertiert. Zum Beispiel wird "SuperSpecialAwesome und auch FizBuzz καιΚάτιΑκόμα" in "super_special_awesome und auch fizz_buzz και_κάτι_ακόμα" konvertiert.
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 hat die unterschiedliche Funktion, das Wort snake_case aus CamelCase zu erstellen.
/**
* 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));
}
Kurze Lösung:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Ich hatte ein ähnliches Problem, konnte jedoch keine Antwort finden, die die Konvertierung von CamelCase in snake_case erfüllt, wobei doppelte oder redundante Unterstriche vermieden wurden _
für Namen mit Unterstrichen oder alle .
Das Problem ist wie folgt:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
Die Lösung, die ich geschrieben habe, ist ein einfacher Aufruf mit zwei Funktionen: Kleinbuchstaben und Suchen und Ersetzen nach aufeinanderfolgenden Kleinbuchstaben in Großbuchstaben:
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}
(oder $name[$k]
) auf Zeichen zugreifen , wodurch Ihr Code länger wird, aber der große Aufwand für die Konvertierung in und aus einem Array vermieden wird.
Die schlechteste Antwort hier war so nah dran, die beste zu sein (benutze ein Framework). NEIN NICHT, schauen Sie sich einfach den Quellcode an. Zu sehen, was ein gut etabliertes Framework verwendet, wäre ein weitaus zuverlässigerer Ansatz (bewährt). Das Zend-Framework verfügt über einige Wortfilter, die Ihren Anforderungen entsprechen. Quelle .
Hier sind einige Methoden, die ich aus der Quelle angepasst habe.
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");
Es gibt eine Bibliothek, die diese Funktionalität bietet:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Wenn Sie das Laravel-Framework verwenden, können Sie nur die Methode snake_case () verwenden.
Dies ist eine der kürzeren Möglichkeiten:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
So entkamelisieren Sie ohne 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;
}
Eine Bearbeitung:
Wie würde ich das 2019 machen:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
Und wenn PHP 7.4 veröffentlicht wird:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
Mit den Filterklassen der Zend Word-Filter ist dies ganz einfach :
<?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
einfach >>> einfach
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
einfach >>> einfach
HTML >>> HTML
simpleXML >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLELast >>> start_middle_last
AString >>> a_string
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
Die Open-Source-TurboCommons-Bibliothek enthält eine universelle formatCase () -Methode innerhalb der StringUtils-Klasse, mit der Sie einen String in viele gängige Groß- und Kleinschreibung wie CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case und viele mehr konvertieren können.
https://github.com/edertone/TurboCommons
Um es zu verwenden, importieren Sie die Phar-Datei in Ihr Projekt und:
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
WENN Sie beginnen könnten mit:
$string = 'Camel_Case'; // underscore or any other separator...
Dann könnten Sie in beide Fälle konvertieren, nur mit:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
Oder andere Fälle:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case