Nếu tôi có:
$string = "PascalCase";
tôi cần
"pascal_case"
PHP có cung cấp một chức năng cho mục đích này không?
Nếu tôi có:
$string = "PascalCase";
tôi cần
"pascal_case"
PHP có cung cấp một chức năng cho mục đích này không?
Câu trả lời:
Hãy thử điều này cho kích thước:
$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);
}
Đầu ra:
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
Điều này thực hiện các quy tắc sau:
Một giải pháp ngắn hơn: Tương tự như giải pháp của trình soạn thảo với biểu thức chính quy đơn giản hóa và khắc phục sự cố "dấu gạch dưới":
$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
Trình diễn PHP | Bản giới thiệu Regex
Lưu ý rằng các trường hợp như SimpleXML
sẽ được chuyển đổi sang simple_x_m_l
sử dụng giải pháp trên. Điều đó cũng có thể được coi là sử dụng sai ký hiệu trường hợp lạc đà (chính xác SimpleXml
) chứ không phải là lỗi của thuật toán vì các trường hợp như vậy luôn mơ hồ - ngay cả khi nhóm các ký tự viết hoa thành một chuỗi ( simple_xml
) thuật toán như vậy sẽ luôn thất bại trong các trường hợp cạnh khác những từ thích XMLHTMLConverter
hoặc một chữ cái gần chữ viết tắt, v.v ... Nếu bạn không bận tâm về các trường hợp cạnh (khá hiếm) và muốn xử lý SimpleXML
chính xác, bạn có thể sử dụng một giải pháp phức tạp hơn một chút:
$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
Một giải pháp ngắn gọn và có thể xử lý một số trường hợp sử dụng khó khăn:
function decamelize($string) {
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}
Có thể xử lý tất cả các trường hợp sau:
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
Bạn có thể kiểm tra chức năng này tại đây: http://syframework.alwaysdata.net/decamelize
Chuyển từ Ruby String#camelize
và 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);
}
Một mẹo mà các giải pháp trên có thể đã bỏ lỡ là công cụ sửa đổi 'e' gây ra preg_replace
để đánh giá chuỗi thay thế dưới dạng mã PHP.
e
lá cờ cho preg_replace
là bị phản đối trong PHP 5.5.
^|
hoặc strlen
.
Các Symfony Serializer Component có CamelCaseToSnakeCaseNameConverter rằng có hai phương pháp normalize()
và denormalize()
. Chúng có thể được sử dụng như sau:
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
echo $nameConverter->normalize('camelCase');
// outputs: camel_case
echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
$nameConverter->normalize('CamelCase')
đầu ra _camel_case
trong phiên bản 3.2 hiện tại của Thành phần nối tiếp Symfony.
Hầu hết các giải pháp ở đây đều cảm thấy nặng tay. Đây là những gì tôi sử dụng:
$underscored = strtolower(
preg_replace(
["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"],
["_$1", "_$1_$2"],
lcfirst($camelCase)
)
);
"CamelCASE" được chuyển đổi thành "camel_case"
lcfirst($camelCase)
sẽ hạ thấp ký tự đầu tiên (tránh đầu ra được chuyển đổi 'CamelCASE' để bắt đầu bằng dấu gạch dưới)[A-Z]
tìm chữ in hoa+
sẽ coi mọi chữ hoa liên tiếp là một từ (tránh 'CamelCASE' được chuyển đổi thành camel_C_A_S_E)ThoseSPECCases
-> those_spec_cases
thay vìthose_speccases
strtolower([…])
biến đầu ra thành chữ thườnglcfirst
chức năng vào $ camelCase
ucfirst()
cuộc gọi. USADollarSymbol
trở thành bản u_sa_dollar_symbol
Demo Tôi không đề xuất giải pháp này vì nó phải thực hiện hai lần đi qua chuỗi đầu vào với regex - một dấu hiệu của một mẫu chưa tinh chỉnh.
php không cung cấp chức năng tích hợp cho afaik này, nhưng đây là những gì tôi sử dụng
function uncamelize($camel,$splitter="_") {
$camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
return strtolower($camel);
}
bộ chia có thể được chỉ định trong lệnh gọi hàm, vì vậy bạn có thể gọi nó như vậy
$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
mb_strtolower
và /u
tùy chọn trên preg_replace
.
Bạn cần chạy regex thông qua nó khớp với mọi chữ cái viết hoa trừ khi nó ở đầu và thay thế nó bằng dấu gạch dưới cộng với chữ cái đó. Một giải pháp utf-8 là thế này:
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_áááá_őőőő
Nếu bạn không chắc chắn trường hợp chuỗi của bạn là gì, tốt hơn là kiểm tra nó trước, bởi vì mã này giả định rằng đầu vào là camelCase
thay vì underscore_Case
hoặc dash-Case
, vì vậy nếu các latters có chữ in hoa, nó sẽ thêm dấu gạch dưới cho chúng.
Câu trả lời được chấp nhận từ cletus là imho quá phức tạp và nó chỉ hoạt động với các ký tự Latin. Tôi thấy đó là một giải pháp thực sự tồi tệ và tự hỏi tại sao nó lại được chấp nhận. Chuyển đổi TEST123String
thành test123_string
không nhất thiết là một yêu cầu hợp lệ. Tôi thà giữ nó đơn giản và tách ra ABCccc
vào a_b_cccc
thay vì ab_cccc
bởi vì nó thông tin không mất theo cách này và việc chuyển đổi ngược sẽ cung cấp cho các chuỗi chính xác cùng chúng tôi bắt đầu với. Ngay cả khi bạn muốn làm theo cách khác, việc viết regex cho nó với giao diện tích cực (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}
hoặc hai regex không có lookbehind là tương đối dễ dàng nếu bạn không phải là chuyên gia về regex. Không cần phải chia nó thành các chuỗi con, chưa kể đến việc quyết định giữa strtolower
và lcfirst
nơi sử dụng strtolower
sẽ hoàn toàn tốt.
Nếu bạn đang tìm kiếm một phiên bản PHP 5.4 và sau đó trả lời ở đây là mã:
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
);
}
Không lạ mắt chút nào nhưng đơn giản và nhanh chóng như địa ngục:
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
thay vì $i++
sẽ làm cho nó nhanh hơn một chút nữa;)
"CamelCase" thành "camel_case":
function camelToSnake($camel)
{
$snake = preg_replace('/[A-Z]/', '_$0', $camel);
$snake = strtolower($snake);
$snake = ltrim($snake, '_');
return $snake;
}
hoặc là:
function camelToSnake($camel)
{
$snake = preg_replace_callback('/[A-Z]/', function ($match){
return '_' . strtolower($match[0]);
}, $camel);
return ltrim($snake, '_');
}
this-kind-of-output
Phiên bản không sử dụng regex có thể được tìm thấy trong nguồn 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);
}
Vì vậy, đây là một lót:
strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));
g
sửa đổi cho regex này.
g
và nó hoạt động tốt với tôi.
g
. Nhưng tôi không thể nhớ cụm từ tôi đã thử nghiệm.
danielstjules / Stringy đã chứng minh một phương pháp để chuyển đổi chuỗi từ camelcase sang snakecase.
s('TestUCase')->underscored(); // 'test_u_case'
Laravel 5.6 cung cấp một cách rất đơn giản để làm điều này:
/**
* 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;
}
Nó làm gì: nếu nó thấy rằng có ít nhất một chữ cái in hoa trong chuỗi đã cho, nó sử dụng một cái nhìn tích cực để tìm kiếm bất kỳ ký tự ( .
) nào theo sau là chữ in hoa ( (?=[A-Z])
). Sau đó, nó thay thế ký tự tìm thấy bằng giá trị của nó, theo sau là dấu phân cách _
.
Cổng trực tiếp từ đường ray (trừ xử lý đặc biệt của họ cho :: hoặc từ viết tắt) sẽ là
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, '-', '_'));
}
Biết PHP, điều này sẽ nhanh hơn so với phân tích cú pháp thủ công xảy ra trong các câu trả lời khác được đưa ra ở đây. Nhược điểm là bạn không được chọn sử dụng phân tách giữa các từ, nhưng đó không phải là một phần của câu hỏi.
Cũng kiểm tra mã nguồn đường ray có liên quan
Lưu ý rằng điều này được thiết kế để sử dụng với các định danh ASCII. Nếu bạn cần thực hiện việc này với các ký tự nằm ngoài phạm vi ASCII, hãy sử dụng công cụ sửa đổi '/ u' cho preg_match
và sử dụng mb_strtolower
.
Đây là đóng góp của tôi cho một câu hỏi sáu năm tuổi với chúa biết có bao nhiêu câu trả lời ...
Nó sẽ chuyển đổi tất cả các từ trong chuỗi được cung cấp trong camelcase thành snakecase. Ví dụ: "SuperecialAwgie và cả FizBuzz κiatedΚάτιΑκόμα" sẽ được chuyển đổi thành "super_special_awemme và cả fizz_buzz κiated_κάτι_ακόμα".
mb_strtolower(
preg_replace_callback(
'/(?<!\b|_)\p{Lu}/u',
function ($a) {
return "_$a[0]";
},
'SuperSpecialAwesome'
)
);
Yii2 có chức năng khác nhau để tạo từ Snake_case từ 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));
}
Giải pháp ngắn gọn:
$subject = "PascalCase";
echo strtolower(preg_replace('/\B([A-Z])/', '_$1', $subject));
Tôi đã gặp một vấn đề tương tự nhưng không thể tìm thấy bất kỳ câu trả lời nào thỏa mãn cách chuyển đổi CamelCase thành Snake_case, đồng thời tránh trùng lặp hoặc thừa các dấu gạch dưới _
cho các tên có dấu gạch dưới hoặc tất cả các chữ viết tắt.
Vấn đề như sau:
CamelCaseClass => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ => faq
Giải pháp tôi đã viết là một hàm đơn giản gọi, viết thường và tìm kiếm và thay thế cho các chữ cái viết thường liên tiếp:
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}
(hoặc $name[$k]
), điều này sẽ làm cho mã của bạn dài hơn, nhưng tránh được chi phí lớn khi chuyển đổi nó sang và từ một mảng.
Câu trả lời tồi tệ nhất ở đây là gần như là tốt nhất (sử dụng khung). KHÔNG KHÔNG, chỉ cần xem mã nguồn. nhìn thấy những gì một khung công tác được thiết lập tốt sẽ là một cách tiếp cận đáng tin cậy hơn nhiều (đã thử và thử nghiệm). Khung Zend có một số bộ lọc từ phù hợp với nhu cầu của bạn. Nguồn .
đây là một vài phương pháp tôi điều chỉnh từ nguồn.
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");
Nếu bạn sử dụng khung công tác Laravel, bạn có thể chỉ sử dụng phương thức sn_case () .
Đây là một trong những cách ngắn hơn:
function camel_to_snake($input)
{
return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}
Cách khử camelize mà không cần sử dụng 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;
}
Một chỉnh sửa:
Làm thế nào tôi sẽ làm điều đó vào năm 2019:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
return $glue . strtolower($matches[0]);
}, $str);
}
Và khi PHP 7.4 sẽ được phát hành:
function toSnakeCase($str, $glue = '_') {
return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}
Thật dễ dàng khi sử dụng các lớp Bộ lọc của Bộ lọc Word Zend :
<?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;
}
}
----- gạch dưới ToCamelCase -----
Simple_test >>> SimpleTest
dễ dàng >>> Dễ dàng
html >>> Html
đơn giản_xml >>> SimpleXml
pdf_load >>> Tải xuống PdfLoad
start_middle_last >>> StartMiddleLast
a_ chuỗi >>> AString
some4_numbers234 >>> some4Numbers234
test123_ chuỗi >>> Test123String
----- camelCaseToUnderscore -----
đơn giản >>> đơn giản
dễ dàng >>> dễ dàng
HTML >>> html
SimpleXML >>> Simple_xml
Tải xuống PDF >>> pdf_load
startMIDDLELast >>> start_middle_last
Bắt buộc >>> a_ chuỗi
Một số4Numbers234 >>> some4_numbers234
TEST123String >>> test123_ chuỗi
Thư viện TurboCommons mã nguồn mở chứa một phương thức định dạng mục đích chungCase () bên trong lớp StringUtils, cho phép bạn chuyển đổi một chuỗi thành nhiều định dạng trường hợp phổ biến, như CamelCase, UpperCamelCase, LowerCamelCase, Snake_case, Title Case, và nhiều hơn nữa.
https://github.com/edertone/TurboCommons
Để sử dụng nó, hãy nhập tệp phar vào dự án của bạn và:
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
NẾU bạn có thể bắt đầu với:
$string = 'Camel_Case'; // underscore or any other separator...
Sau đó, bạn có thể chuyển đổi sang một trong hai trường hợp chỉ với:
$pascal = str_replace("_", "", $string);
$snake = strtolower($string);
Hoặc bất kỳ trường hợp nào khác:
$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string); // CAMEL_CASE
$train = str_replace("_", "-", $snake); // camel-case