如何将PascalCase转换为snake_case?

2022-08-30 06:59:24

如果我有:

$string = "PascalCase";

我需要

"pascal_case"

PHP是否为此目的提供了函数?


答案 1

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

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

PHP 演示|正则表达式演示


请注意,此类情况将转换为使用上述解决方案。这也可以被认为是驼峰大小写符号的错误用法(正确的将是),而不是算法的错误,因为这种情况总是模棱两可的 - 即使通过将大写字符分组为一个字符串(),这种算法在其他边缘情况下总是会失败,例如或缩写附近的一个字母单词等。如果您不介意(相当罕见的)边缘情况并希望正确处理,则可以使用更复杂的解决方案:SimpleXMLsimple_x_m_lSimpleXmlsimple_xmlXMLHTMLConverterSimpleXML

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

PHP 演示|正则表达式演示


答案 2

试试这个尺寸:

$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. 以大写字母开头的序列可以后跟以下任一代码:
    • 一个或多个大写字母和数字(后跟字符串的结尾或大写字母,后跟小写字母或数字,即下一个序列的开头);或
    • 一个或多个小写字母或数字。

推荐