Frage

Wenn ich:

$string = "PascalCase";

Ich brauche

"pascal_case"

Does PHP bietet eine Funktion für diesen Zweck?

War es hilfreich?

Lösung

Versuchen Sie, diese für Größe:

$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. Eine Sequenz mit einem Kleinbuchstaben beginnen müssen von Kleinbuchstaben und Ziffern folgen;
  2. Eine Sequenz mit einem Großbuchstaben beginnen kann entweder folgen:
    • ein oder mehr Großbuchstaben und Ziffern (gefolgt von entweder das Ende der Schnur oder einen Großbuchstaben von einem Kleinbuchstabe oder Ziffer dh den Start der nächsten Sequenz folgte); oder
    • eine oder mehrere Kleinbuchstaben und Ziffern.

Andere Tipps

Eine kürzere Lösung: ähnlich wie bei der Redaktion ein mit einem vereinfachten regulären Ausdruck und zur Festsetzung des „nachlaufStrich“ Problem:

$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));

PHP Demo | Regex Demo


Beachten Sie, dass Fälle wie SimpleXML wird simple_x_m_l unter Verwendung der obigen Lösung umgewandelt werden. Das kann auch eine falsche Verwendung von Kamel Fall Notation in Betracht gezogen werden (korrekter SimpleXml wäre), anstatt ein Fehler des Algorithmus, da solche Fälle sind immer mehrdeutig - auch durch Großbuchstaben Gruppierung zu einer Zeichenkette (simple_xml) solcher Algorithmus wird immer in andere scheitern Grenzfälle wie XMLHTMLConverter oder ein-Buchstaben-Worte in der Nähe von Abkürzungen, etc. Wenn Sie nicht über die (eher selten) Grenzfälle und wollen Griff SimpleXML richtig nichts ausmachen, können Sie eine wenig komplexe Lösung verwenden:

$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');

PHP Demo | Regex Demo

Eine kurze Lösung und kann einige schwierige Anwendungsfälle behandeln:

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 testen hier: http://syframework.alwaysdata.net/decamelize

Portierte von Rubys 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, die oben genannten Lösungen verpaßt haben ist das ‚e‘ Modifikator, die preg_replace bewirkt, dass der Ersatz-String als PHP-Code bewerten.

Die Symfony Serializer Komponente eine CamelCaseToSnakeCaseNameConverter das hat 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

Die meisten Lösungen hier fühlen sich schwer handed. Hier ist, was ich benutze:

$underscored = strtolower(
    preg_replace(
        ["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"], 
        ["_$1", "_$1_$2"], 
        lcfirst($camelCase)
    )
);

"Camelcase" auf "camel_case" umgewandelt

  • lcfirst($camelCase) wird das erste Zeichen (Vermeidet ‚Camelcase‘ konvertierte Ausgabe beginnen mit einem Unterstrich)
  • senken
  • [A-Z] findet Großbuchstaben
  • + wird jeden aufeinanderfolgende Großbuchstaben als Wort behandelt (Vermeidet ‚Camelcase‘ zu camel_C_A_S_E umgewandelt werden)
  • Zweites Muster und Ersatz ist für ThoseSPECCases -> those_spec_cases statt those_speccases
  • strtolower([…]) schaltet die Ausgabe in Kleinbuchstaben

PHP nicht bieten eine für diese afaik in Funktion gebaut, aber hier ist das, was ich

function uncamelize($camel,$splitter="_") {
    $camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
    return strtolower($camel);

}

der Splitter kann in dem Funktionsaufruf angegeben werden, so dass Sie es wie so nennen können

$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_áááá_őőőő

Wenn Sie eine PHP 5.4 Version suchen und später hier beantworten ist 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
    );

} 

Nichts Besonderes an alle, 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

"Camelcase" auf "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, '_');
}

Eine Version, die nicht regex nicht verwenden kann, in der Alchitect Quelle gefunden werden:

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

So, hier ist ein Einzeiler:

strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));

danielstjules / Stringy provieds ein Verfahren zum Konvertieren von Zeichenfolge von Camelcase zu snakecase.

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 er sieht, dass es zumindest einen Großbuchstaben in der gegebenen Zeichenkette, verwendet es eine positive Vorschau für ein beliebiges Zeichen (.) zu suchen, gefolgt von einem Großbuchstaben ((?=[A-Z])). Es ersetzt dann die gefundenen Zeichen mit seinem Wert durch die separactor _ gefolgt.

Der direkte Anschluss von Schienen (minus ihre Sonderbehandlung 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, '-', '_'));
}

Zu wissen, PHP, wird dies schneller als die manuelle Analyse, die in anderen hier gegebenen Antworten passiert. Der Nachteil ist, dass Sie nicht als Trennzeichen zwischen Worten, was dem Einsatz wählen haben, aber das war nicht Teil der Frage.

Überprüfen Sie auch die entsprechenden Schienen Quelle Code

Beachten Sie, dass diese für die Verwendung mit ASCII-Identifikatoren vorgesehen ist. Wenn Sie dies mit Zeichen tun, müssen außerhalb des ASCII-Bereichs, verwenden Sie die ‚/ u‘ Modifikator für preg_matchand Verwendung mb_strtolower.

Hier ist mein Beitrag zu einem sechs Jahre alten Frage mit Gott weiß, wie viele Antworten ...

Es werden alle Wörter in der mitgelieferten Zeichenfolge konvertieren, die in Camelcase zu snakecase sind. Zum Beispiel "SuperSpecialAwesome und FizBuzz καιΚάτιΑκόμα auch" wird umgewandelt werden "super_special_awesome und auch fizz_buzz και_κάτι_ακόμα".

mb_strtolower(
    preg_replace_callback(
        '/(?<!\b|_)\p{Lu}/u',
        function ($a) {
            return "_$a[0]";
        },
        'SuperSpecialAwesome'
    )
);

Yii2 haben die andere Funktion das Wort snake_case von Camelcase zu machen.

    /**
     * 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);
}

Es gibt eine Bibliothek bietet diese Funktionalität:

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"

Wenn Sie Laravel Framework verwenden, können Sie einfach snake_case () Methode.

$str = 'FooBarBaz';

return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz

Dies ist ein kürzeren Wege:

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}

Wie de-camelize 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;
}

Ein edit:

Wie würde ich das tue im Jahr 2019:

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 wird freigegeben:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}

Kurz Lösung:

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

Es ist einfach, die Filter-Klassen des Zend Wort Filter :

<?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 >>> Simple

     

leicht >>> Leicht

     

html >>> Html

     

simple_xml >>> SimpleXML

     

pdf_load >>> PdfLoad

     

start_middle_last >>> StartMiddleLast

     

a_string >>> AString

     

some4_numbers234 >>> Some4Numbers234

     

test123_string >>> Test123String

     

----- ----- camelCaseToUnderscore

     

Simple >>> simple_test

     

leicht >>> einfach

     

HTML >>> html

     

SimpleXML >>> simple_xml

     

PDFLoad >>> pdf_load

     

startMIDDLELast >>> start_middle_last

     

AString >>> a_string

     

Some4Numbers234 >>> some4_numbers234

     

TEST123String >>> test123_string

Die schlechteste Antwort auf hier war so nah, der Beste zu sein (ein Framework verwenden). NO dies nicht tun, nur einen Blick auf den Quellcode. zu sehen, was ein gut etabliertes Framework verwendet ein weitaus zuverlässigen Ansatz wäre (bewährten). Das Zend Framework hat einige Wortfilter, die Ihre Bedürfnisse anzupassen. Quelle .

Hier ist ein paar Methoden, die ich von der Quelle angepasst.

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

Die Open-Source-TurboCommons Bibliothek enthält einen Mehrzweck formatCase () -Methode in der StringUtils-Klasse, die Sie eine Zeichenfolge zu vielen häufigeren Fall Formate konvertieren kann, wie Camelcase, Uppercamelcase, LowerCamelCase, snake_case, Titel Case, und viele mehr.

https://github.com/edertone/TurboCommons

Um es zu verwenden, importieren Sie die phar Datei zu Ihrem Projekt und:

use org\turbocommons\src\main\php\utils\StringUtils;

echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);

// will output 'camel_Case'

Ich hatte ein ähnliches Problem, aber konnte keine Antwort finden, dass befriedigt, wie Camelcase zu snake_case konvertieren, während die Vermeidung doppelter oder redundanter Unterstrichen für Namen mit Unterstrichen _ oder alle Kappen Abkürzungen.

Th Problem ist wie folgt:

CamelCaseClass            => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ                       => faq

Die Lösung, die ich geschrieben habe, ist eine einfache zwei Funktionen aufrufen, Klein-und suchen und für aufeinanderfolgende Klein-Großbuchstaben ersetzt werden:

strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));

Wenn Sie könnte beginnen mit:

$string = 'Camel_Case'; // underscore or any other separator...

Dann könnte man auf jeden Fall umbauen mit:

$pascal = str_replace("_", "", $string);
$snake = strtolower($string);

oder eine beliebige andere Fälle:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top