在跳过缩写时,将camel case格式化为可在PHP中读取

时间:2017-11-22 09:20:46

标签: php regex camelcasing

所以我被困 - 我在这里看了很多答案,但似乎没有解决我的最后一个问题。

通过带有JSON的API,我收到了一个camelcase格式的设备列表。我不能改变它。

我需要将这个camelcase翻译成普通语言 -

到目前为止,我已经将大部分单词分开了:

$string = "SomeEquipmentHere";

$spaced = preg_replace('/([A-Z])/', ' $1', $string);
var_dump($spaced);

string ' Some Equipment Here' (length=20)

$trimmed = trim($spaced);
var_dump($trimmed);
string 'Some Equipment Here' (length=19)

哪种工作正常 - 但在某些设备中包含缩写

“ABSBrakes” - 这需要ABS并与制动器分开

我无法检查彼此相邻的几个大写字母,因为它会将ABS和制动器保持在一起 - 还有更多像这样,即:“CDRadio”

所需要的是输出:

"ABS Brakes"

有没有办法对它进行格式化,如果彼此旁边有大写字母,那么只在该序列的最后一个大写字母前加一个空格?

我在正则表达方面并不强大。

修改

这两个贡献都很棒 - 以后来这里的人应该读两个答案

最后的问题包括以下模式:

“ServiceOK”变为“Service O K”

“ESP”成为“ES P”

仅由纯大写字母缩写组成的模式由计数小写字母的函数修复,如果没有,则跳过preg_replace()。

但正如Flying在他的回答的评论中写道的那样,他的正则表达式可能会有很多实例未被覆盖,并且答案可能是不可能的 - 我不知道这对正则表达式是否是一个挑战。

可能通过添加一些“如果大写后没有小写,则不应该插入空格”规则

2 个答案:

答案 0 :(得分:3)

以下是如何解决的问题:

$tests = [
    'SomeEquipmentHere',
    'ABSBrakes',
    'CDRadio',
    'Valve14',
];
foreach ($tests as $test) {
    echo trim(preg_replace('/\s+/', ' ', preg_replace('/([A-Z][a-z]+)|([A-Z]+(?=[A-Z]))|(\d+)/', '$1 $2 $3', $test)));
    echo "\n";
}

regex101上的相关测试。

更新:添加了其他问题的示例

答案 1 :(得分:2)

这是一个单一调用模式,它不使用替换字符串中的任何锚点,捕获组或引用:/(?:[a-z]|[A-Z]+)\K(?=[A-Z]|\d+)/

Pattern&Replace Demo

代码:(Demo

$tests = [
    'SomeEquipmentHere',
    'ABSBrakes',
    'CDRadio',
    'Valve14',
];
foreach ($tests as $test) {
    echo preg_replace('/(?:[a-z]|[A-Z]+)\K(?=[A-Z]|\d+)/',' ',$test),"\n";
}

输出:

Some Equipment Here
ABS Brakes
CD Radio
Valve 14

这是一种更好的方法,因为没有什么可以清理的。如果有新的字符串要考虑(这会破坏我的方法),请将它们留在评论中,以便我可以更新我的模式。

模式说明:

/         #start the pattern
(?:[a-z]  #match 1 lowercase letter
|         #or
[A-Z]+)   #1 or more uppercase letters
\K        #restart the fullstring match (forget the past)
(?=[A-Z]  #look-ahead for 1 uppercase letter
|         #or
\d+)      #1 or more digits
/         #end the pattern

编辑:

还有一些其他模式可以提供更好的准确性,包括:

/(?:[a-z]|\B[A-Z]+)\K(?=[A-Z]\B|\d+)/

当然,上述模式无法正确处理ServiceOK

Demo Link Word Boundaries Link

或带锚的这种模式:

/(?!^)(?=[A-Z][a-z]+|(?<=\D)\d)/

上述模式将按照OP的要求准确分割:SomeEquipmentHereABSBrakesCDRadioValve14ServiceOKESP

Demo Link

*注意:随着提供更多样本字符串,可以提高模式的准确性。