PascalCase를 pascal_case로 변환하는 방법?


답변:


163

크기를 위해 이것을 시도하십시오 :

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

산출:

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

이는 다음 규칙을 구현합니다.

  1. 소문자로 시작하는 시퀀스 뒤에는 소문자와 숫자가 와야합니다.
  2. 대문자로 시작하는 시퀀스 뒤에 다음 중 하나가 올 수 있습니다.
    • 하나 이상의 대문자 및 숫자 (문자열의 끝 또는 대문자 다음에 소문자 또는 숫자, 즉 다음 시퀀스의 시작) 또는
    • 하나 이상의 소문자 또는 숫자.

9
CamelCased 문자열 (openfrog이 요청한대로)에 대해 작동하지만 예를 들어 "r_id"(이미 "underscored")와 같은 입력 문자열과 함께 사용하면 접두사 ( "r_")를 잘라냅니다. 좋은 솔루션이지만 보편적이지 않습니다.
Martin

1
문자열이 모두 대문자 문자열과 일치하는지 확인하는 이유가 궁금하십니까? 모든 문자가 아닌 첫 번째 문자 만 소문자로 변환하면 어떤 이점이 있습니까?
Josh

1
이러한 모든 사용 사례를 처리 할 수있는보다 간결한 솔루션 : stackoverflow.com/a/35719689/4328383
Syone

156

더 짧은 솔루션 : 단순화 된 정규 표현식을 사용하고 "후행 밑줄"문제를 수정하는 편집기의 솔루션과 유사합니다 .

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

PHP 데모 | Regex 데모


이와 같은 경우 는 위의 솔루션 SimpleXMLsimple_x_m_l사용하여 변환됩니다 . 또한 SimpleXml이러한 경우는 항상 모호하기 때문에 알고리즘의 버그 라기보다는 낙타 대소 문자 표기법 (정답은 ) 의 잘못된 사용으로 간주 될 수 있습니다. 대문자를 하나의 문자열 ( simple_xml) 로 그룹화하더라도 이러한 알고리즘은 항상 다른 경우에 실패합니다. XMLHTMLConverter약어 근처에있는 like 또는 한 글자 단어 등. (아주 드문 경우) 엣지 케이스에 대해 신경 쓰지 않고 SimpleXML올바르게 처리 하려면 좀 더 복잡한 솔루션을 사용할 수 있습니다.

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

PHP 데모 | Regex 데모


어떤 테스트 케이스를 수정했는지 자세히 설명하는 cletus의 답변에 자유롭게 의견을 말하십시오.
Mike B

3
나는 그의 솔루션이 잘못된 결과를 제공한다고 말하는 것이 아닙니다. 그의 솔루션은 매우 복잡하고 비효율적입니다.
월 제이크

1
네, 수락 대답은 확실히 실패입니다. Jan의 솔루션은 굉장합니다! 참고로이 질문에 대해 실제로 작동하지 않는 답변의 수가 엄청 나기 때문에이 (또는 약간의 변형)이 PHP 개발자에게 가장 좋아하는 새로운 코딩 테스트라고 생각합니다. 초기 필터링을 수행하는 좋은 방법이 될 것입니다. :-)
JamesG 2015-08-05

이 솔루션에 사용 된 정규식이 훨씬 더 완전하다는 것을 발견했습니다. stackoverflow.com/questions/2559759/…
thoroc

2
간단한 사용 사례를위한 좋은 솔루션이며 대부분의 일반적인 경우 충분하지만 허용 된 솔루션은 더 많은 사용 사례를 처리 할 수 ​​있습니다. 예를 들어 "simpleXML"은 "simple_x_m_l"이 아닌 "simple_xml"로 변환 될 수 있습니다.
Syone

35

간결한 솔루션이며 까다로운 사용 사례를 처리 할 수 ​​있습니다.

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}

다음 모든 경우를 처리 할 수 ​​있습니다.

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

이 기능은 여기에서 테스트 할 수 있습니다 : http://syframework.alwaysdata.net/decamelize


@VivekVardhan이 정규식의 어느 부분을 이해하지 못합니까?
Syone

음, 카멜 케이스가 아닌 문자열을 소문자로 지정하는 것은 부작용이라고 생각합니다. 문자열이 카멜 케이스 형식이 아닌 경우 원래 문자열이 반환되어야합니다. 사실 'simple_Text'를 보내면 Fail : simple_Test => simple_Test [simple_test]가 표시됩니다. 소문자 문자열은 원래 문자열 만 실제 카멜 케이스 문자열 인 경우에만 만들어야합니다. 당신은 무엇을 생각합니까?
guido

24

Ruby String#camelizeString#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); 
}

위의 솔루션이 놓쳤을 수있는 한 가지 트릭은 preg_replace대체 문자열을 PHP 코드로 평가하는 'e'수정 자입니다 .


10
에 대한 e플래그 preg_replace는 PHP 5.5에서 더 이상 사용되지 않습니다.
cdmckay

BTW 이것들은 Ruby에도 없지만 Rails의 inflector 라이브러리-camelize and underscore에 있습니다. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
mahemoff

2
이것은 "ThisIsATest"에 대해 실패합니다. 연속 된 두 대문자를 지원하지 않는 것 같습니다.
OnaBai

참고 : lcfirst를 사용하여 첫 글자를 소문자로 바꿀 수 있습니다. 그런 다음 ^|또는 strlen.
Benubird


23

심포니 시리얼 구성 요소CamelCaseToSnakeCaseNameConverter 두 가지 방법이있다 normalize()denormalize(). 다음과 같이 사용할 수 있습니다.

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

echo $nameConverter->normalize('camelCase');
// outputs: camel_case

echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase

1
조심하세요! Symfony Serializer Component의 현재 버전 3.2에서 $nameConverter->normalize('CamelCase')출력 _camel_case합니다.
spackmat

21

여기에있는 대부분의 솔루션은 무겁게 느껴집니다. 내가 사용하는 것은 다음과 같습니다.

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

"CamelCASE"는 "camel_case"로 변환됩니다.

  • lcfirst($camelCase) 첫 번째 문자를 낮 춥니 다 ( 'CamelCASE'로 변환 된 출력이 밑줄로 시작하지 않도록합니다)
  • [A-Z] 대문자를 찾습니다
  • + 연속 된 모든 대문자를 단어로 처리합니다 ( 'CamelCASE'가 camel_C_A_S_E로 변환되는 것을 방지 함).
  • 두 번째 패턴 및 대체는 ThoseSPECCases-> those_spec_cases대신those_speccases
  • strtolower([…]) 출력을 소문자로 바꿉니다.

3
그러나 그것은 또한 CamelCased를 _camel_cased로 바꿉니다.
acme

1
이것은 훌륭합니다-그 문제를 해결하기 위해 char 1에서 시작하는 substr을 추가하십시오.
Oddman 2013 년

4
훌륭합니다! lcfirst$ camelCase 에 함수 를 추가 하면됩니다
Edakos

받아 들여진 대답은 다음을 처리 할 것입니다 : TestUPSClass를 test_ups_class로 바꾸고 이것은 그것을 염두에 두어야 할 test_u_p_s_class로 바꿀 것입니다.
Mazzy

대문자로 시작하는 첫 번째 "단어"로 시작하는 입력 문자열은 ucfirst()호출 로 인해이 솔루션에 의해 예기치 않게 분할됩니다 . USADollarSymbol가된다 u_sa_dollar_symbol 데모 미정 제 패턴의 기호 - 그것은 정규식 입력 문자열을 통해 두 개의 패스를 가지고 있기 때문에이 솔루션을 사용하지 않는 것이 좋습니다.
mickmackusa

19

PHP는이 afaik에 대한 내장 기능을 제공하지 않지만 여기에 내가 사용하는 것이 있습니다.

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

}

스플리터는 함수 호출에 지정할 수 있으므로 이렇게 호출 할 수 있습니다.

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"

2
이것은 "ThisIsATest"에 대해 실패합니다. 연속 된 두 대문자를 지원하지 않는 것 같습니다.
OnaBai

두 번째 교체가 아무것도하지 않기 때문에 확실히 당신은 무언가를 잊었습니다. 이 외에도에서, 당신은 쉽게와 호환 유니 코드 수 mb_strtolower/u에 옵션 preg_replace.
bodo

8

시작 부분에있는 경우를 제외하고 모든 대문자와 일치하는 정규식을 실행하고 언더 스크 로어와 해당 문자로 대체해야합니다. utf-8 솔루션은 다음과 같습니다.

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

문자열이 어떤 대소 문자인지 확실하지 않은 경우 먼저 확인하는 것이 좋습니다.이 코드는 입력이 또는 camelCase대신 있다고 가정 하므로 후자에 대문자가 있으면 밑줄이 추가됩니다.underscore_Casedash-Case

cletus에서 받아 들여지는 대답은 너무 복잡하고 imho이며 라틴 문자에서만 작동합니다. 나는 그것이 정말 나쁜 해결책이라고 생각하고 그것이 왜 받아 들여 졌는지 궁금합니다. 변환 TEST123String으로하는 것은 test123_string반드시 유효한 요구하지 않습니다. 차라리 간단하게 유지하고 분리 ABCccca_b_cccc대신 ab_cccc그렇지 잃게 정보이 방법을 수행하고 역방향 변환 우리가 시작 동일한 문자열을 줄 것 때문이. 다른 방식으로하고 싶은 경우에도 (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}정규식 전문가가 아닌 경우 긍정적 인 lookbehind 또는 두 개의 정규식을 사용하여 정규식을 작성하는 것이 상대적으로 쉽습니다 . 사용하는 것이 완전히 괜찮을 위치 strtolower와 사이를 결정하는 것은 말할 것도없고 하위 문자열로 분할 할 필요가 없습니다 .lcfirststrtolower


코드 전용 답변은 수천 명의 미래 연구원을 교육 / 권한을 부여하는 데 거의 수행하지 않기 때문에 Stackoverflow에서 가치가 낮습니다.
mickmackusa

@mickmackusa 연구원이 SO에서 코딩하는 방법을 배우면 심각한 문제가 있습니다 ...
inf3rno

이제 시스템에서 개인 공격을 받았으므로 답변을 개선하십시오. 솔루션의 작동 방식과 이러한 패턴 수정자를 사용하는 이유를 알고 있다고 가정 할 때이 커뮤니티에서 지식을 보류 할 이유가 없습니다. 더 은밀한 답변을 남기는 것을 고려하고 있다면, 그들이 나를 괴롭히지 않는다고 확신합니다. 당신이 댓글을 달았을 때, 당신은 당신의 답변을 완성하고, 우리는 우리의 댓글을 삭제할 수 있었고, 나는이 사이트를 돕기 위해 다른 곳으로 갈 수도있었습니다.
mickmackusa

물론, 8 개의 찬성 게시물을 삭제할 권한이 없습니다. 원하는 경우 답변을 삭제할 수 있지만 불필요한 패턴 수정자를 제거하고 설명을 추가하여 간단히 개선하는 것은 그리 어렵지 않습니다. 인신 공격은 나에게 영향을 미치지 않습니다.
mickmackusa

@mickmackusa 나도 그것을 삭제할 수 있다고 생각하지 않습니다. 원하는 경우 자유롭게 편집하십시오.
inf3rno

6

PHP 5.4 버전 이상을 찾고 있다면 여기에 코드가 있습니다.

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

} 

sms_sent에 대한 낙타 생산 "SmsSent", 당신은 lcfirst가 필요합니다
mik3fly-4steri5k

4

전혀 화려하지는 않지만 지옥처럼 간단하고 빠릅니다.

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대신 $i++뿐만 아니라 그것을 조금 더 빠른을 할 것이다)
마티유 Amiot

코드 전용 답변은 수천 명의 미래 연구원을 교육 / 권한을 부여하는 데 거의하지 않기 때문에 Stackoverflow에서 가치가 낮습니다.
mickmackusa

4

"CamelCase"에서 "camel_case"로 :

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $camel);
    $snake = strtolower($snake);
    $snake = ltrim($snake, '_');
    return $snake;
}

또는:

function camelToSnake($camel)
{
    $snake = preg_replace_callback('/[A-Z]/', function ($match){
        return '_' . strtolower($match[0]);
    }, $camel);
    return ltrim($snake, '_');
}

감사합니다. 첫 번째 접근 방식을 사용했지만 하이픈을 사용하여 생성했습니다this-kind-of-output
thexpand

3

정규식을 사용하지 않는 버전은 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);
}

2
이것은 생명이 같은 :-) 정규식없이 될 것입니다
ekhaled

4
헤, 그래. RegEx는 확실히 장점이 있습니다. :) 원시 속도는 그중 하나가 아닙니다.
Darrell Brogdon

어떤 이유로이 하나 몇 가지 재미있는 결과를 얻었다
mr1031011

이 문자열을 기반으로 작동하지 않습니다 : "CamelCaseTestAAATestAA", 있어야합니다 : "camel_case_test_a_a_a_test_a_a", has : ""camel_case_test_aest "...
Sybio

3

그래서 여기에 한 줄짜리가 있습니다.

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

좋지만 첫 번째 모습 만 변환 g하므로이 정규식에 수정자를 추가하는 것이 좋습니다 .
acme

@acme, 나는 그것을 사용하지 않고 g잘 작동합니다.
seelts

제 경우에는 어떤 이유로 g. 하지만 제가 테스트 한 문구가 기억 나지 않습니다.
acme


3

Laravel 5.6은이를 수행하는 매우 간단한 방법을 제공합니다.

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

기능 : 주어진 문자열에 대문자가 하나 이상있는 것을 확인하면 긍정적 인 미리보기를 사용합니다.. 하여 대문자 ( )가 뒤 따르는 문자 ( ) 를 검색합니다 (?=[A-Z]). 그런 다음 찾은 문자를 값 뒤에 구분 기호가있는 값으로 바꿉니다 _.


이 함수는 이제 snake_case ()라고 불리며 전역 네임 스페이스에 있습니다.
Wotuu

2

레일의 직접 포트 (:: 또는 약어에 대한 특수 처리 제외)는 다음과 같습니다.

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

PHP를 알면 여기에 제공된 다른 답변에서 발생하는 수동 구문 분석보다 빠릅니다. 단점은 단어 사이의 구분자로 사용할 것을 선택할 수 없다는 것입니다. 그러나 그것은 질문의 일부가 아닙니다.

관련 레일 소스 코드 도 확인하십시오.

이것은 ASCII 식별자와 함께 사용하기위한 것입니다. ASCII 범위를 벗어난 문자로이 작업을 수행해야하는 경우 '/ u'수정자를 preg_match사용하고 mb_strtolower.


원하는 문자가 포함 된 매개 변수를 간단히 추가 할 수 있습니다.
Fleshgrinder 2014

2

여섯 살짜리 질문에 대한 나의 공헌은 하나님이 얼마나 많은 답을 알고 있는지 알고 있습니다 ...

camelcase에있는 제공된 문자열의 모든 단어를 snakecase로 변환합니다. 예를 들어 "SuperSpecialAwesome 및 FizBuzz καιΚάτιΑκόμα"는 "super_special_awesome 및 fizz_buzz και_κάτι_ακόμα"로 변환됩니다.

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

2

Yii2는 CamelCase에서 snake_case라는 단어를 만드는 다른 기능을 가지고 있습니다.

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


2

비슷한 문제가 있었지만 중복 또는 중복 밑줄을 피하면서 CamelCase를 snake_case로 변환하는 방법을 만족시키는 답을 찾을 수 없었습니다. _ 이있는 이름이나 모두 대문자 약어에 대해 을 .

문제는 다음과 같습니다.

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

내가 작성한 솔루션은 소문자와 연속 소문자 대문자 검색 및 바꾸기라는 간단한 두 가지 함수를 호출하는 것입니다.

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

지금까지 이것은 가장 간결하고 유용한 솔루션 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);
}

$name{$k}(또는 $name[$k])을 사용하여 문자에 직접 액세스 할 수 있습니다. 이렇게하면 코드가 더 길어 지지만 배열과 배열간에 변환하는 큰 오버 헤드를 피할 수 있습니다.
bodo

코드 전용 답변은 미래 연구자에게 권한을 부여 / 교육하는 일을 제대로 수행하지 못하기 때문에 StackOverflow에서 가치가 낮습니다. 귀하의 솔루션은 정규식의 은혜를 피하면서 매우 무겁고 복잡합니다. 모든 문자를 분할하고 여러 반복 함수를 호출합니다. 빈 문자열을 접착제로 지정할 필요가 없습니다. 우아함, 낮은 가독성 및 n 개의 불필요한 함수 호출 이 없기 때문에 내 프로젝트 중 하나에서이 솔루션을 사용하지 않을 것 입니다.
mickmackusa

1

여기에 대한 최악의 대답은 최고 (프레임 워크 사용)에 너무 가깝습니다. 아니요, 소스 코드를 살펴보십시오. 잘 확립 된 프레임 워크가 사용하는 것을 보는 것이 훨씬 더 신뢰할 수있는 접근 방식 (시도 및 테스트)이 될 것입니다. Zend 프레임 워크에는 필요에 맞는 몇 가지 단어 필터가 있습니다. 소스 .

다음은 소스에서 채택한 몇 가지 방법입니다.

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

1

이 기능을 제공 하는 라이브러리 가 있습니다.

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

1
"이 기능을 제공하는 라이브러리를 만들었습니다"라는 뜻이라고 생각합니다. 자기 홍보에는 문제가 없지만 숨기지 마십시오.
icc97


1

이것은 더 짧은 방법 중 하나입니다.

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

코드 전용 답변은 수천 명의 미래 연구원을 교육 / 권한을 부여하는 데 거의하지 않기 때문에 Stackoverflow에서 가치가 낮습니다.
mickmackusa

1
@mickmackusa-수천 개의 미래 연구가 우아한 한 줄에 관심을 갖고 스스로를 교육 할 것입니다.
Teson

이기적인 입장을 취해 죄송합니다. 그 비열한 답장을 디자인하고 입력하는 데 걸린 시간에 대한 설명을 추가했을 수도 있습니다. 귀하의 답변은 세 번의 함수 호출을 수행하지만 다른 사용자는 두 번의 작업을 수행합니다.
mickmackusa

1

정규식을 사용하지 않고 낙타를 제거하는 방법 :

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

편집 :

2019 년에는 어떻게할까요?

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

그리고 PHP 7.4가 출시 될 때 :

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

1
코드 전용 답변은 미래 연구자에게 권한을 부여 / 교육하는 일을 제대로 수행하지 못하기 때문에 StackOverflow에서 가치가 낮습니다. 문자열의 모든 문자에 대해 1 ~ 3 개의 함수 호출을 수행하고 루프가 완료된 후 두 번 이상의 함수 호출을 수행하는 것은 매우 어렵습니다. 경제가 그렇게 좋지 않은 상황에서는 해결책을 찾지 못할 것입니다.
mickmackusa

프로덕션에서 사용하는 방법이 아니라 정규식을 사용하지 않고 수행 할 수있는 방법의 예이므로 하나의 찬성표가 있고 다음과 같이 표시 될 가능성이없는 5 년 / o 답변에 대해 불평한다는 점 외에는 귀하의 요점이 보이지 않습니다. 모든 연구원.
baldrs

나는 투표가 많은 게시물이나 최근 게시물뿐만 아니라 모든 게시물에 관심을 기울입니다. 나는 불평하는 것이 아니라 지식이 적은 연구원 이이 답변과 다른 답변의 차이점을 더 잘 이해할 수 있도록 내 비판을 제공합니다. 귀하의 게시물에서 정규식을 피하는 것은 학문적 도전 일 뿐이라고 설명 할 수 있습니다. 즉, 더 나은 코딩 방법으로이 프로세스를보다 효율적으로 만드는 방법이 있습니다.
mickmackusa

0

Zend Word Filters 의 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 >>> SimpleTest

쉬움 >>> 쉬움

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

쉽게 >>> 쉽게

HTML >>> html

simpleXML >>> simple_xml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

AString >>> a_string

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string


0

오픈 소스 TurboCommons 라이브러리에는 StringUtils 클래스 내에 범용 formatCase () 메서드가 포함되어있어 문자열을 CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case 등과 같은 많은 일반적인 케이스 형식으로 변환 할 수 있습니다.

https://github.com/edertone/TurboCommons

이를 사용하려면 phar 파일을 프로젝트로 가져오고 다음을 수행하십시오.

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

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

// will output 'camel_Case'

0
$str = 'FooBarBaz';

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

1
코드 전용 답변은 미래 연구자에게 권한을 부여 / 교육하는 일을 제대로 수행하지 못하기 때문에 StackOverflow에서 가치가 낮습니다.
mickmackusa

-1

다음으로 시작할 수 있다면 :

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

그런 다음 다음과 같이 두 경우 중 하나로 변환 할 수 있습니다.

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

또는 다른 경우 :

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.