Wie konvertiere ich PascalCase in pascal_case?

115

Hätte ich:

$string = "PascalCase";

Ich brauche

"pascal_case"

Bietet PHP eine Funktion für diesen Zweck?

offener Frosch
quelle
31
Technisch gesehen ist die erste Beispielzeichenfolge PascalCase.
Robin van Baalen
33
Die zweite Beispielzeichenfolge heißt snake_case .
Pang

Antworten:

163

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:

  1. Auf eine Sequenz, die mit einem Kleinbuchstaben beginnt, müssen Kleinbuchstaben und Ziffern folgen.
  2. Einer Sequenz, die mit einem Großbuchstaben beginnt, kann folgendermaßen folgen:
    • ein oder mehrere Großbuchstaben und Ziffern (gefolgt vom Ende der Zeichenfolge oder einem Großbuchstaben, gefolgt von einem Kleinbuchstaben oder einer Ziffer, dh dem Beginn der nächsten Sequenz); oder
    • ein oder mehrere Kleinbuchstaben oder Ziffern.
Cletus
quelle
9
Es funktioniert für CamelCased-Zeichenfolgen (wie von openfrog gefragt), aber wenn Sie es mit einer Eingabezeichenfolge verwenden, z. B. "r_id" (bereits "unterstrichen"), wird das Präfix ("r_") gekürzt. Gute Lösung, aber definitiv nicht universell.
Martin
1
Neugierig, warum Sie prüfen, ob die Zeichenfolge mit der Zeichenfolge mit Großbuchstaben übereinstimmt? Was ist der Vorteil, wenn nur das erste Zeichen in Kleinbuchstaben konvertiert wird (im Gegensatz zu allen Zeichen)?
Josh
1
Eine präzisere
Syone
155

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));

PHP Demo | Regex Demo


Beachten Sie, dass Fälle wie SimpleXMLdie simple_x_m_lVerwendung 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- XMLHTMLConverteroder 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 SimpleXMLrichtig 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)), '_');

PHP Demo | Regex Demo

Jan Jakeš
quelle
Fühlen Sie sich frei, die Antwort von cletus zu kommentieren, in der angegeben ist, welche Testfälle Sie behoben haben.
Mike B
3
Ich sage nicht, dass seine Lösung falsche Ergebnisse liefert. Seine Lösung ist nur äußerst kompliziert und ineffektiv.
Jan Jakeš
1
Ja, die Antwort ist definitiv ein Fehlschlag. Jan's Lösung ist großartig! Als Randnotiz denke ich, dass dies (oder eine geringfügige Abweichung) mein neuer, bevorzugter Codierungstest für PHP-Entwickler ist, da die Anzahl der Antworten auf diese Frage, die nicht wirklich funktionieren, unglaublich ist. Es wäre eine großartige Möglichkeit, die anfängliche Filterung durchzuführen. :-)
JamesG
fand den in dieser Lösung verwendeten regulären
Ausdruck
2
Gute Lösung für einfache Anwendungsfälle und in den meisten Fällen reicht es aus, aber die akzeptierte Lösung kann mehr Anwendungsfälle verarbeiten. Beispielsweise kann "simpleXML" in "simple_xml" und nicht in "simple_x_m_l"
konvertiert werden
35

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

Syone
quelle
@VivekVardhan Welchen Teil dieser Regex verstehst du nicht?
Syone
Ähm, ich denke, dass das Verringern von Nicht-Camelcase-Zeichenfolgen ein Nebeneffekt ist, falls die Zeichenfolge nicht im Camelcase-Format vorliegt, sollte die ursprüngliche zurückgegeben werden. Wenn Sie 'simple_Text' senden, erhalten Sie Fail: simple_Test => simple_Test [simple_test]. Die Zeichenfolge in Kleinbuchstaben sollte nur erstellt werden, und wenn nur die ursprüngliche Zeichenfolge eine echte Kamelkastenzeichenfolge ist. Was denkst du über?
Guido
24

Portiert von Ruby's String#camelizeund 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.

user644783
quelle
10
Das eFlag für preg_replacewird in PHP 5.5 veraltet.
CDMckay
Übrigens sind diese auch nicht in Ruby, sondern in der Inflector-Bibliothek von Rails - Kamelisieren und Unterstreichen. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
Mahemoff
2
Dies schlägt für "ThisIsATest" fehl. Scheint, dass zwei aufeinanderfolgende Großbuchstaben nicht unterstützt werden.
OnaBai
Nur eine Anmerkung: Sie können lcfirst verwenden, um den ersten Buchstaben in Kleinbuchstaben zu schreiben, dann brauchen Sie das ^|oder nicht strlen.
Benubird
ohne Veralterung
Scones
23

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
Matthew
quelle
1
In acht nehmen! $nameConverter->normalize('CamelCase')Ausgaben _camel_casein der aktuellen Version 3.2 der Symfony Serializer-Komponente.
Spackmat
21

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)
  • Zweites Muster und Ersatz sind für ThoseSPECCases-> those_spec_casesstattthose_speccases
  • strtolower([…]) Schaltet die Ausgabe in Kleinbuchstaben um
buley
quelle
3
Aber es wird auch CamelCased zu _camel_cased.
Acme
1
Das ist großartig - fügen Sie einfach einen Teil ab Zeichen 1 hinzu, um dieses Problem zu umgehen.
Oddman
4
Hervorragend! Nur müssen hinzufügen lcfirstFunktion $ Camelcase
Edakos
Die akzeptierte Antwort lautet: TestUPSClass in test_ups_class, während dies in test_u_p_s_class umgewandelt wird, was zu beachten ist.
Mazzy
Eine Eingabezeichenfolge, die mit dem ersten "Wort" von allcaps beginnt, wird von dieser Lösung aufgrund des ucfirst()Aufrufs unerwartet aufgeteilt . USADollarSymbolwird 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.
Mickmackusa
19

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"
ekhaled
quelle
2
Dies schlägt für "ThisIsATest" fehl. Scheint, dass zwei aufeinanderfolgende Großbuchstaben nicht unterstützt werden.
OnaBai
Sicher haben Sie etwas vergessen, da der zweite Ersatz nichts bewirkt. Abgesehen davon können Sie es einfach Unicode-kompatibel machen mb_strtolowerund die /uOption aktivieren preg_replace.
Bodo
8

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 camelCaseanstelle von underscore_Caseoder 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 TEST123Stringin test123_stringist nicht unbedingt eine gültige Voraussetzung. Ich eher hielt es einfach und getrennt ABCcccin a_b_ccccstatt , ab_ccccweil 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 strtolowerund lcfirstwo die Verwendung nur strtolowervöllig in Ordnung wäre.

inf3rno
quelle
Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa
@mickmackusa Wenn Forscher lernen, wie man aus SO codiert, dann haben wir ein ernstes Problem ...
inf3rno
Nachdem Sie diesen persönlichen Angriff von Ihrem System erhalten haben, verbessern Sie bitte Ihre Antwort. Angenommen, Sie wissen, wie Ihre Lösung funktioniert und warum Sie diese Mustermodifikatoren verwenden, sehe ich keinen guten Grund, dieser Community Wissen vorzuenthalten. Für den Fall, dass Sie erwägen, mehr snarky Antworten zu hinterlassen, versichere ich Ihnen, dass sie mich nicht stören. In der Zeit, die Sie für einen Kommentar benötigt haben, hätten Sie Ihre Antwort vervollständigen können, wir hätten unsere Kommentare löschen können, und ich hätte woanders hingehen können, um dieser Site zu helfen.
Mickmackusa
Natürlich habe ich keine Berechtigung, einen Beitrag mit 8 Upvotes zu löschen. Wenn Sie möchten, können Sie Ihre Antwort löschen, aber es wäre nicht sehr schwierig, sie einfach zu verbessern, indem Sie unnötige Mustermodifikatoren entfernen und eine Erklärung hinzufügen. Die persönlichen Angriffe haben keinen Einfluss auf mich.
Mickmackusa
@mickmackusa Ich glaube nicht, dass ich es auch löschen kann. Fühlen Sie sich frei, es zu bearbeiten, wenn Sie möchten.
inf3rno
6

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
    );

} 
Shacharsol
quelle
camelize produziere "SmsSent" für sms_sent, du brauchst ein erstes
mik3fly-4steri5k
4

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
Edakos
quelle
++$ianstatt $i++würde es auch ein bisschen schneller machen;)
Mathieu Amiot
Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa
4

"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, '_');
}
Xiaojing
quelle
Danke dir. Ich habe den ersten Ansatz verwendet, aber mit Bindestrichen zu generierenthis-kind-of-output
thexpand
3

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);
}
Darrell Brogdon
quelle
1
So würde das Leben ohne Regex
aussehen
4
Heh, ja. RegEx hat definitiv seine Vorteile. :) Rohe Geschwindigkeit gehört nicht dazu.
Darrell Brogdon
habe aus irgendeinem Grund einige lustige Ergebnisse mit diesem
erzielt
Funktioniert nicht für mich basierend auf dieser Zeichenfolge: "CamelCaseTestAAATestAA", sollte haben: "camel_case_test_a_a_a_test_a_a", hat: "" camel_case_test_aest "...
Sybio
3

Also hier ist ein Einzeiler:

strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
seelts
quelle
Schön, aber es konvertiert nur das erste Erscheinungsbild, daher würde ich empfehlen g, diesem regulären Ausdruck einen Modifikator hinzuzufügen .
Acme
@acme, ich benutze es ohne gund es funktioniert gut für mich.
Seelts
Aus irgendeinem Grund musste ich in meinem Fall das hinzufügen g. Aber ich kann mich nicht an den Satz erinnern, mit dem ich getestet habe.
Acme
3

danielstjules / Stringy hat eine Methode zum Konvertieren von Strings von Camelcase in Snakecase bereitgestellt.

s('TestUCase')->underscored(); // 'test_u_case'
Jimmy Ko
quelle
3

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 _.

Valdrinium
quelle
Diese Funktion scheint nun snake_case () zu heißen und befindet sich im globalen Namespace.
Wotuu
2

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_matchund verwenden Sie mb_strtolower.

Pilif
quelle
Sie könnten, wenn Sie einfach einen Parameter hinzufügen, der das gewünschte Zeichen enthält.
Fleischwolf
2

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'
    )
);
Loupax
quelle
2

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));
    }
Anil Chaudhari
quelle
2

Kurze Lösung:

$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Gevorg Melkumyan
quelle
2

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));
MMSs
quelle
Dies ist bei weitem die prägnanteste und nützlichste Lösung IMO.
Mr.Shan0
1
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);
}
Kurt Zhong
quelle
Sie können direkt mit $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.
Bodo
Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden. Ihre Lösung vermeidet zwar die Anmut von Regex, ist jedoch sehr hartnäckig und verworren. Sie teilen jedes Zeichen auf und führen mehrere iterierte Funktionsaufrufe durch. Es ist nicht erforderlich, eine leere Schnur als Klebstoff zu benennen. Ich würde diese Lösung in einem meiner Projekte nicht in Betracht ziehen, da es keine Eleganz, geringe Lesbarkeit und n unnötige Funktionsaufrufe gibt.
Mickmackusa
1

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");
TarranJones
quelle
1

Es gibt eine Bibliothek, die diese Funktionalität bietet:

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Kolyunya
quelle
1
Ich denke, Sie meinen "Ich habe eine Bibliothek erstellt, die diese Funktionalität bietet". An Eigenwerbung ist nichts auszusetzen, aber verstecken Sie sie nicht.
icc97
1

Wenn Sie das Laravel-Framework verwenden, können Sie nur die Methode snake_case () verwenden.

Marek Skiba
quelle
1

Dies ist eine der kürzeren Möglichkeiten:

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Ayman Gado
quelle
Nur-Code-Antworten sind für Stackoverflow von geringem Wert, da sie nur sehr wenig dazu beitragen, Tausende zukünftiger Forscher auszubilden / zu befähigen.
Mickmackusa
1
@mickmackusa - Tausende von zukünftigen Forschungen werden sich für einen eleganten Einzeiler interessieren und sich selbst ausbilden.
Teson
Es tut mir leid, dass Sie diese egoistische Haltung eingenommen haben. Sie hätten sicherlich eine Erklärung in der Zeit hinzufügen können, die Sie für das Entwerfen und Eingeben dieser snarky Antwort benötigt haben. Ihre Antwort führt drei Funktionsaufrufe aus, andere führen die Aufgabe in zwei Schritten aus.
Mickmackusa
1

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);
}
Glatzen
quelle
1
Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden. Das Ausführen von 1 bis 3 Funktionsaufrufen für jedes Zeichen in der Zeichenfolge und zwei weitere Funktionsaufrufe nach Abschluss der Schleife ist sehr schwierig. Ich würde keine Lösung mit solch einer schlechten Wirtschaft finden.
Mickmackusa
Es ist ein Beispiel dafür, wie es ohne die Verwendung regulärer Ausdrücke gemacht werden könnte, nicht wie es in der Produktion verwendet werden sollte. Ich verstehe Ihren Standpunkt nicht, außer dass Sie sich über eine 5-jährige Antwort beschweren, die eine positive Bewertung hat und von der es unwahrscheinlich ist, dass sie gesehen wird irgendwelche Forscher.
Baldrs
Ich widme mich allen Beiträgen, nicht nur den hoch bewerteten oder den jüngsten. Ich beschwere mich nicht, ich biete meine Kritik an, damit Forscher mit weniger Wissen den Unterschied zwischen dieser Antwort und anderen Antworten besser verstehen können. Sie hätten in Ihrem Beitrag erklären können, dass es lediglich eine akademische Herausforderung war, Regex zu vermeiden. Es gibt jedoch Möglichkeiten, diesen Prozess durch bessere Codierungspraktiken effizienter zu gestalten.
Mickmackusa
0

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

automatix
quelle
0

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'
Jaume Mussons Abad
quelle
0
$str = 'FooBarBaz';

return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz
Omar Makled
quelle
1
Nur-Code-Antworten sind für StackOverflow von geringem Wert, da sie zukünftige Forscher nur schlecht befähigen / ausbilden.
Mickmackusa
-1

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
Nuno Rafael Figueiredo
quelle