驼峰式大写 - 两个大写字母彼此相邻

问题描述 投票:0回答:4

我正在使用此函数将 CamelCase 转换为虚线字符串:

function camel2dashed($className) {
    return strtolower(preg_replace('/([^A-Z-])([A-Z])/', '$1-$2', $className));
}

它有点管用,但是当我有前任时就会出现问题。该字符串:

getADog
。它返回
get-adog
但我想要
get-a-dog

我应该如何更改我的代码?谢谢

php regex camelcasing kebab-case
4个回答
38
投票

使用前瞻断言

function camel2dashed($className) {
    return strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $className));
}

查看它在线运行:ideone


8
投票

如果您知道字符串不是以大写字母开头,则不需要先行断言来执行此操作,只需在每个大写字母之前插入连字符,如下所示:

function camel2dashed($className) {
    return strtolower(preg_replace('/([A-Z])/', '-$1', $className));
}

这仍然无法处理像 @sfjedi 的“companyHQ”->“company-hq”这样的情况。为此,您必须显式测试是否允许不应拆分的大写子字符串,或指定一些通用规则(例如,不要在最后一个字符之前添加连字符)。

您可以在这个虚拟重复问题的答案中找到一些更复杂的替代方案。


0
投票
function camel2dash($name) {
   return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $name)), '-');
}

有望处理所有边缘情况:

SomeOfTheWords → some-of-the-words
getADog → get-a-dog
ADog → a-dog
aDog → a-dog
XML → xml
SimpleXMLReader → simple-xml-reader

0
投票

您的

camelCase
kebab-case
模式不需要捕获任何内容或在替换中使用反向引用。

代码:(演示

$className = 'getADog';
echo strtolower(preg_replace('/[a-zA-Z]\K(?=[A-Z])/', '-', $className));
// get-a-dog

要获得更强大的正则表达式,可以处理驼峰命名法和 StudlyCase 命名法,并正确处理首字母缩略词和数字字符串,请尝试以下操作。 (演示)

(?>               #start atomic group (use first qualifying branch)
   [A-Z]?[a-z]+   #zero or one upper followed by one or more lowers
   |              #OR
   [A-Z]+         #one or more uppers
   (?=            #start lookahead without consuming characters
      [A-Z][a-z]  #one upper followed by one lower
      |           #OR
      [^A-Za-z]   #one non-letter
   )              #end lookahead
   |              #OR
   [^A-Za-z]+     #one or more non-letters
)                 #end atomic group
\K                #forget any consumed matched characters so far
(?!$)             #position must not be the end of the string

代码:(演示

$tests = [
    'getADogThenROCKInTheUSA',
    'SomeOfTheWords',
    'getADog',
    'ADog',
    'aDog',
    'XML',
    'SimpleXMLReader',
    'FREE4NOW',
    '123ABC',
    'DEF456',
    'ghi789',
    'wtf666Omg',
    'PHP8Point3',
    
];
foreach ($tests as $test) {
    printf(
        "%25s => %s\n",
        $test,
        strtolower(
            preg_replace(
                '/(?>[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|[^A-Za-z])|[^A-Za-z]+)\K(?!$)/',
                '-',
                $test
            )
        )
    );
}

输出:

  getADogThenROCKInTheUSA => get-a-dog-then-rock-in-the-usa
           SomeOfTheWords => some-of-the-words
                  getADog => get-a-dog
                     ADog => a-dog
                     aDog => a-dog
                      XML => xml
          SimpleXMLReader => simple-xml-reader
                 FREE4NOW => free-4-now
                   123ABC => 123-abc
                   DEF456 => def-456
                   ghi789 => ghi-789
                wtf666Omg => wtf-666-omg
               PHP8Point3 => php-8-point-3
© www.soinside.com 2019 - 2024. All rights reserved.