将正则表达式组合以将camelCase字符串拆分为单词

4

我成功地实现了一个将驼峰式命名转换为单词的函数,使用了@ridgerunner在这个问题中提出的解决方案:

使用PHP preg_match(正则表达式)将camelCase单词拆分为单词

然而,我还想处理嵌入式缩写,像这样:

'hasABREVIATIONEmbedded' 翻译为 'Has ABREVIATION Embedded'

我想到了这个解决方案:

    <?php 

    function camelCaseToWords($camelCaseStr)
    {

        // Convert: "TestASAPTestMore" to "TestASAP TestMore"

        $abreviationsPattern = '/' . // Match position between UPPERCASE "words"
            '(?<=[A-Z])' . // Position is after group of uppercase,
            '(?=[A-Z][a-z])' . // and before group of lowercase letters, except the last upper case letter in the group.
            '/x';
        $arr = preg_split($abreviationsPattern, $camelCaseStr);
        $str = implode(' ', $arr);

        // Convert "TestASAP TestMore" to "Test ASAP Test More"
        $camelCasePattern = '/' . // Match position between camelCase "words".
            '(?<=[a-z])' . // Position is after a lowercase,
            '(?=[A-Z])' . // and before an uppercase letter.
            '/x';

        $arr = preg_split($camelCasePattern, $str);
        $str = implode(' ', $arr);

        $str = ucfirst(trim($str));
        return $str;
    }

    $inputs = array(
    'oneTwoThreeFour',
    'StartsWithCap',
    'hasConsecutiveCAPS',
    'ALLCAPS',
    'ALL_CAPS_AND_UNDERSCORES',
    'hasABREVIATIONEmbedded',
    );

    echo "INPUT";

    foreach($inputs as $val) {
        echo "'" . $val . "' translates to '" . camelCaseToWords($val). "'\n";
    }

输出结果为:
    INPUT'oneTwoThreeFour' translates to 'One Two Three Four'
    'StartsWithCap' translates to 'Starts With Cap'
    'hasConsecutiveCAPS' translates to 'Has Consecutive CAPS'
    'ALLCAPS' translates to 'ALLCAPS'
    'ALL_CAPS_AND_UNDERSCORES' translates to 'ALL_CAPS_AND_UNDERSCORES'
    'hasABREVIATIONEmbedded' translates to 'Has ABREVIATION Embedded'

它按预期工作。

我的问题是: 我能否将两个正则表达式$abreviationsPattern和camelCasePattern结合起来, 以便我可以避免两次运行preg_split()函数吗?


为什么您在通过连接操作和使用PHP注释而不是正则表达式注释避免所有空格的情况下,仍然要使用 x 修饰符?x 的重点是您可以将表达式作为一个多行字符串传递,并带有 #... 注释。 - Martin Ender
我不知道\x的含义。我从提到的源代码中复制了该模式,并在此基础上进行了扩展。感谢您的信息。 - stou
1个回答

1

这些难题总是很有趣的,我已经将案例缩小到了两个:

  1. 检测以大写字母开头后跟小写字母的单词(但不是以单词边界或主题开头)- (?<!\b)[A-Z][a-z]+

  2. 检测从小写字母到大写字母的转换 - (?<=[a-z])[A-Z]

    function camelFix($str)
    {
        return preg_replace_callback('/(?<!\b)[A-Z][a-z]+|(?<=[a-z])[A-Z]/', function($match) {
            return ' '. $match[0];
        }, $str);
    }
    
它适用于你提供的输入;可能会在我未预见到的情况下失败 :)

谢谢。运行得很好。我知道肯定有比我能想出来的更好的解决方案 :-) 必须使用create_function()来允许在php5.2上运行,并且用ucfirst()包装了一下。 - stou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接