Jika saya memiliki:
$string = "PascalCase";
saya butuh
"pascal_case"
Apakah PHP menawarkan fungsi untuk tujuan ini?
Jika saya memiliki:
$string = "PascalCase";
saya butuh
"pascal_case"
Apakah PHP menawarkan fungsi untuk tujuan ini?
Jawaban:
Coba ini untuk ukuran:
$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);
}
Keluaran:
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
Ini menerapkan aturan berikut:
Solusi yang lebih singkat: Mirip dengan solusi editor dengan ekspresi reguler yang disederhanakan dan memperbaiki masalah "trailing-underscore":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Perhatikan bahwa kasus seperti SimpleXML
akan diubah simple_x_m_l
menggunakan solusi di atas. Itu juga dapat dianggap sebagai penggunaan notasi huruf besar yang salah (benar akan SimpleXml
) daripada bug algoritma karena kasus seperti itu selalu ambigu - bahkan dengan mengelompokkan karakter huruf besar ke satu string ( simple_xml
) algoritma seperti itu akan selalu gagal dalam kasus tepi lainnya seperti XMLHTMLConverter
atau kata satu huruf dekat singkatan, dll. Jika Anda tidak keberatan tentang kasus tepi (agak jarang) dan ingin menangani SimpleXML
dengan benar, Anda dapat menggunakan solusi yang sedikit lebih kompleks:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Solusi singkat dan dapat menangani beberapa kasus penggunaan yang rumit:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
Dapat menangani semua kasus ini:
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
Anda dapat menguji fungsi ini di sini: http://syframework.alwaysdata.net/decamelize
Diangkut dari Ruby String#camelize
dan 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);
}
Salah satu trik yang mungkin terlewatkan oleh solusi di atas adalah pengubah 'e' yang menyebabkan preg_replace
mengevaluasi string pengganti sebagai kode PHP.
e
bendera untuk preg_replace
yaitu yang usang dalam PHP 5.5.
^|
atau strlen
.
The Symfony Serializer Komponen memiliki CamelCaseToSnakeCaseNameConverter yang memiliki dua metode normalize()
dan denormalize()
. Ini dapat digunakan sebagai berikut:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
$nameConverter->normalize('CamelCase')
output _camel_case
dalam versi 3.2 dari Symfony Serializer Component.
Sebagian besar solusi di sini terasa berat. Inilah yang saya gunakan:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_$1", "_$1_$2"],
lcfirst($camelCase)
)
);
"CamelCASE" diubah menjadi "camel_case"
lcfirst($camelCase)
akan menurunkan karakter pertama (hindari keluaran yang dikonversi 'CamelCASE' untuk memulai dengan garis bawah)[A-Z]
menemukan huruf kapital+
akan memperlakukan setiap huruf besar yang berurutan sebagai sebuah kata (hindari 'CamelCASE' untuk diubah menjadi camel_C_A_S_E)ThoseSPECCases
->, those_spec_cases
bukanthose_speccases
strtolower([…])
mengubah keluaran menjadi huruf kecillcfirst
fungsi ke $
ucfirst()
panggilan tersebut. USADollarSymbol
menjadi u_sa_dollar_symbol
Demo Saya tidak merekomendasikan solusi ini karena harus membuat dua lintasan melalui string input dengan regex - tanda pola yang tidak dimurnikan.
php tidak menawarkan fungsi bawaan untuk afaik ini, tapi inilah yang saya gunakan
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
return strtolower($camel);
}
splitter dapat ditentukan dalam pemanggilan fungsi, sehingga Anda dapat memanggilnya seperti itu
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
dan /u
opsi aktif preg_replace
.
Anda perlu menjalankan regex yang cocok dengan setiap huruf besar kecuali di awal dan menggantinya dengan garis bawah ditambah huruf itu. Solusi utf-8 adalah ini:
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_áááá_őőőő
Jika Anda tidak yakin dengan huruf besar apa string Anda, lebih baik periksa dulu, karena kode ini mengasumsikan bahwa masukannya camelCase
bukan underscore_Case
atau dash-Case
, jadi jika latters memiliki huruf besar, itu akan menambahkan garis bawah ke dalamnya.
Jawaban yang diterima dari cletus terlalu rumit dan hanya berfungsi dengan karakter latin. Saya merasa itu solusi yang sangat buruk dan bertanya-tanya mengapa itu diterima sama sekali. Mengubah TEST123String
menjadi test123_string
belum tentu merupakan persyaratan yang valid. Saya lebih suka membuatnya sederhana dan dipisahkan ABCccc
menjadi a_b_cccc
bukan ab_cccc
karena tidak kehilangan informasi dengan cara ini dan konversi mundur akan memberikan string yang sama persis dengan yang kita mulai. Meskipun Anda ingin melakukannya dengan cara lain, relatif mudah untuk menulis regex untuknya dengan tampilan positif (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
atau dua ekspresi reguler tanpa tampilan belakang jika Anda bukan ahli ekspresi reguler. Tidak perlu membaginya menjadi beberapa substring, apalagi memutuskan antara strtolower
dan di lcfirst
mana menggunakan just strtolower
akan baik-baik saja.
Jika Anda mencari versi PHP 5.4 dan jawaban yang lebih baru di sini adalah kodenya:
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
);
}
Tidak mewah sama sekali tapi sederhana dan cepat sekali:
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
alih-alih $i++
membuatnya sedikit lebih cepat juga;)
"CamelCase" menjadi "camel_case":
function camelToSnake($camel)
{
$snake = preg_replace('/[A-Z]/', '_$0', $camel);
$snake = strtolower($snake);
$snake = ltrim($snake, '_');
return $snake;
}
atau:
function camelToSnake($camel)
{
$snake = preg_replace_callback('/[A-Z]/', function ($match){
return '_' . strtolower($match[0]);
}, $camel);
return ltrim($snake, '_');
}
this-kind-of-output
Versi yang tidak menggunakan regex dapat ditemukan di sumber 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);
}
Jadi ini satu baris:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
g
pengubah ke regex ini.
g
dan berfungsi dengan baik untuk saya.
g
. Tapi saya tidak ingat frase yang saya uji.
danielstjules / Stringy menyediakan metode untuk mengubah string dari camelcase ke snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 menyediakan cara yang sangat sederhana untuk melakukan ini:
/**
* 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;
}
Apa fungsinya: jika terlihat bahwa setidaknya ada satu huruf kapital dalam string yang diberikan, ia menggunakan a lookahead positif untuk mencari karakter apa pun ( .
) diikuti dengan huruf kapital ( (?=[A-Z])
). Ini kemudian menggantikan karakter yang ditemukan dengan nilainya diikuti oleh pemisah _
.
Port langsung dari rel (tanpa penanganan khusus untuk :: atau akronim) akan menjadi
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, '-', '_'));
}
Mengetahui PHP, ini akan lebih cepat daripada penguraian manual yang terjadi di jawaban lain yang diberikan di sini. Kerugiannya adalah Anda tidak bisa memilih apa yang akan digunakan sebagai pemisah antar kata, tetapi itu bukan bagian dari pertanyaan.
Juga periksa kode sumber rel yang relevan
Perhatikan bahwa ini dimaksudkan untuk digunakan dengan pengenal ASCII. Jika Anda perlu melakukan ini dengan karakter di luar rentang ASCII, gunakan pengubah '/ u' untuk preg_match
dan digunakan mb_strtolower
.
Inilah kontribusi saya untuk pertanyaan berusia enam tahun dengan entah berapa banyak jawaban ...
Ini akan mengubah semua kata dalam string yang disediakan yang ada di camelcase menjadi snakecase. Misalnya "SuperSpecialAwesome dan juga FizBuzz καιΚάτιΑκόμα" akan diubah menjadi "super_special_awesome dan juga fizz_buzz και_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 memiliki fungsi berbeda untuk membuat kata snake_case dari 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));
}
Solusi singkat:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Saya memiliki masalah serupa tetapi tidak dapat menemukan jawaban yang memuaskan tentang cara mengonversi CamelCase ke snake_case, sambil menghindari garis bawah duplikat atau berlebihan _
untuk nama dengan garis bawah, atau singkatan huruf besar semua.
Masalahnya adalah sebagai berikut:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
Solusi yang saya tulis adalah panggilan dua fungsi sederhana, huruf kecil dan cari dan ganti untuk huruf kecil-besar yang berurutan:
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}
(atau $name[$k]
), yang akan membuat kode Anda lebih panjang, tetapi menghindari overhead besar untuk mengonversinya ke dan dari larik.
Jawaban terburuk di sini sangat dekat dengan yang terbaik (gunakan kerangka kerja). JANGAN JANGAN, lihat saja kode sumbernya. melihat apa yang digunakan kerangka kerja mapan akan menjadi pendekatan yang jauh lebih andal (dicoba dan diuji). Kerangka Zend memiliki beberapa filter kata yang sesuai dengan kebutuhan Anda. Sumber .
berikut adalah beberapa metode yang saya adaptasi dari sumbernya.
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");
Ada perpustakaan yang menyediakan fungsionalitas ini:
SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"
Jika Anda menggunakan framework Laravel, Anda dapat menggunakan metode snake_case () saja .
Ini adalah salah satu cara yang lebih singkat:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Cara menghapus camelize tanpa menggunakan 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;
}
Sebuah edit:
Bagaimana saya melakukannya di 2019:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
Dan saat PHP 7.4 akan dirilis:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
Sangat mudah menggunakan kelas Filter dari Zend Word Filters :
<?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
mudah >>> Mudah
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
mudah >>> mudah
HTML >>> html
simpleXML >>> simple_xml
PDFLoad >>> pdf_load
startMIDDLETerakhir >>> start_middle_last
AString >>> a_string
Some4Numbers234 >>> some4_numbers234
TEST123String >>> test123_string
Pustaka TurboCommons open source berisi metode formatCase () tujuan umum di dalam kelas StringUtils, yang memungkinkan Anda mengonversi string ke banyak format kasus umum, seperti CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case, dan banyak lagi.
https://github.com/edertone/TurboCommons
Untuk menggunakannya, impor file phar ke proyek Anda dan:
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
JIKA Anda bisa mulai dengan:
$string = 'Camel_Case'; // underscore or any other separator...
Kemudian Anda dapat mengonversi ke salah satu kasus hanya dengan:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
Atau kasus lainnya:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case