cle*_*tus 151

试试这个尺码:

$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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

这实现了以下规则:

  1. 以小写字母开头的序列必须后跟小写字母和数字;
  2. 以大写字母开头的序列可以跟随:
    • 一个或多个大写字母和数字(后跟字符串的结尾或大写字母后跟小写字母或数字,即下一个序列的开头); 要么
    • 一个或多个小写字母或数字.

  • 它适用于CamelCased字符串(如openfrog问),但如果你将它用于输入字符串,例如"r_id"(已经"强调"),则会修剪前缀("r_").好的解决方案,但绝对不是普遍的. (9认同)

Jan*_*keš 138

一个较短的解决方案:类似于编辑器的简化正则表达式并修复"尾随下划线"问题:

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

PHP演示 | 正则表达式演示


请注意,类似的情况SimpleXML将转换为simple_x_m_l使用上述解决方案.这也可以被认为是骆驼案例符号的错误用法(正确的是SimpleXml)而不是算法的错误,因为这种情况总是模糊的 - 即使将大写字符分组到一个字符串(simple_xml)这样的算法在其他边缘情况下总是会失败喜欢XMLHTMLConverter或缩写等单字母的单词等.如果你不介意(相当罕见的)边缘情况并想要SimpleXML正确处理,你可以使用一些更复杂的解决方案:

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

PHP演示 | 正则表达式演示

  • 我不是说他的解决方案会给出错误的结果.他的解决方案非常复杂且无效. (3认同)
  • 是的,接受答案肯定是失败的。Jan 的解决方案太棒了!附带说明一下,我认为这(或略有不同)是我最喜欢的 PHP 开发人员新的编码测试,因为为这个问题提供的实际上不起作用的答案数量令人难以置信。这将是进行初始过滤的好方法。:-) (2认同)
  • 简单的用例,最常见的情况下,很好的解决方案是不够好,但接受的解决方案可以处理更多使用案例,例如"SimpleXML的"可转换为"simple_xml",而不是"simple_x_m_l" (2认同)

Syo*_*one 33

一个简洁的解决方案,可以处理一些棘手的用例:

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

可以处理所有这些情况:

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
Run Code Online (Sandbox Code Playgroud)

你可以在这里测试这个功能:http://syframework.alwaysdata.net/decamelize


小智 24

从Ruby's 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); 
}
Run Code Online (Sandbox Code Playgroud)

上述解决方案可能遗漏的一个技巧是'e'修饰符,它导致preg_replace将替换字符串评估为PHP代码.

  • `preg_replace`的`e`标志在PHP 5.5中被弃用. (10认同)
  • 这对"ThisIsATest"失败了.似乎不支持两个连续的大写. (2认同)

mat*_*hew 23

Symfony的串行组件具有CamelCaseToSnakeCaseNameConverter有两种方法normalize()denormalize().这些可以使用如下:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

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

echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase
Run Code Online (Sandbox Code Playgroud)

  • 谨防!`$nameConverter-&gt;normalize('CamelCase')` 在 Symfony Serializer Component 的当前版本 3.2 中输出 `_camel_case`。 (3认同)

bul*_*ley 20

这里的大多数解决方案都很重要 这是我使用的:

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

"CamelCASE"转换为"camel_case"

  • lcfirst($camelCase) 将降低第一个字符(避免'CamelCASE'转换输出以下划线开头)
  • [A-Z] 找到大写字母
  • + 将每个连续的大写视为一个单词(避免将'CamelCASE'转换为camel_C_A_S_E)
  • 第二种模式和替换是ThoseSPECCases- > those_spec_cases而不是those_speccases
  • strtolower([…]) 将输出转为小写

  • 外观极好!只需要在$ camelCase中添加`lcfirst`函数即可 (4认同)
  • 但它也将CamelCased变为_camel_cased. (3认同)

ekh*_*led 18

php没有为这个afaik提供内置函数,但这是我使用的

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

}
Run Code Online (Sandbox Code Playgroud)

可以在函数调用中指定拆分器,因此可以像这样调用它

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"
Run Code Online (Sandbox Code Playgroud)

  • 这对"ThisIsATest"失败了.似乎不支持两个连续的大写. (2认同)

inf*_*rno 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_áááá_????
Run Code Online (Sandbox Code Playgroud)

(接受的"解决方案"是史诗般的失败......)


xia*_*ing 8

“CamelCase”到“camel_case”:

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

或者:

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


sha*_*sol 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
    );

} 
Run Code Online (Sandbox Code Playgroud)


MMS*_*MSs 6

我有一个类似的问题,但找不到任何满足如何将 CamelCase 转换为 snake_case 的答案,同时避免_带有下划线的名称或所有大写缩写的重复或冗余下划线。

问题如下:

CamelCaseClass            => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ                       => faq
Run Code Online (Sandbox Code Playgroud)

我写的解决方案是一个简单的两个函数调用,小写和搜索并替换连续的小写-大写字母:

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

  • 到目前为止,这是我认为最简洁、最有用的解决方案。 (2认同)

Gev*_*yan 5

简短的解决方案:

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