我如何分割这个词:
oneTwoThreeFour
进入一个数组,这样我就可以得到:
one Two Three Four
与preg_match
?
我厌倦了这个,但它只是给出了整个词
$words = preg_match("/[a-zA-Z]*(?:[a-z][a-zA-Z]*[A-Z]|[A-Z][a-zA-Z]*[a-z])[a-zA-Z]*\b/", $string, $matches)`;
答案 0 :(得分:75)
您也可以将preg_match_all
用作:
preg_match_all('/((?:^|[A-Z])[a-z]+)/',$str,$matches);
说明:
( - Start of capturing parenthesis.
(?: - Start of non-capturing parenthesis.
^ - Start anchor.
| - Alternation.
[A-Z] - Any one capital letter.
) - End of non-capturing parenthesis.
[a-z]+ - one ore more lowercase letter.
) - End of capturing parenthesis.
答案 1 :(得分:69)
您可以将preg_split
用作:
$arr = preg_split('/(?=[A-Z])/',$str);
我基本上是在大写字母之前拆分输入字符串。使用(?=[A-Z])
的正则表达式匹配大写字母之前的点。
答案 2 :(得分:49)
我知道这是一个老问题,有一个公认的答案,但恕我直言,有一个更好的解决方案:
<?php // test.php Rev:20140412_0800
$ccWord = 'NewNASAModule';
$re = '/(?#! splitCamelCase Rev:20140412)
# Split camelCase "words". Two global alternatives. Either g1of2:
(?<=[a-z]) # Position is after a lowercase,
(?=[A-Z]) # and before an uppercase letter.
| (?<=[A-Z]) # Or g2of2; Position is after uppercase,
(?=[A-Z][a-z]) # and before upper-then-lower case.
/x';
$a = preg_split($re, $ccWord);
$count = count($a);
for ($i = 0; $i < $count; ++$i) {
printf("Word %d of %d = \"%s\"\n",
$i + 1, $count, $a[$i]);
}
?>
请注意,这个正则表达式(如codaddict的'/(?=[A-Z])/'
解决方案 - 就像一个很好的形式的camelCase单词的魅力),只匹配字符串中的位置并且根本不消耗任何文本。此解决方案还具有额外的好处,即它也可以正确地用于不完美形成的伪camelcase单词,例如:StartsWithCap
和:hasConsecutiveCAPS
。
oneTwoThreeFour
StartsWithCap
hasConsecutiveCAPS
NewNASAModule
Word 1 of 4 = "one"
Word 2 of 4 = "Two"
Word 3 of 4 = "Three"
Word 4 of 4 = "Four"
Word 1 of 3 = "Starts"
Word 2 of 3 = "With"
Word 3 of 3 = "Cap"
Word 1 of 3 = "has"
Word 2 of 3 = "Consecutive"
Word 3 of 3 = "CAPS"
Word 1 of 3 = "New"
Word 2 of 3 = "NASA"
Word 3 of 3 = "Module"
编辑:2014-04-12:修改正则表达式,脚本和测试数据以正确拆分:"NewNASAModule"
案例(响应rr的评论)。
答案 3 :(得分:12)
@ ridgerunner答案的功能化版本。
/**
* Converts camelCase string to have spaces between each.
* @param $camelCaseString
* @return string
*/
function fromCamelCase($camelCaseString) {
$re = '/(?<=[a-z])(?=[A-Z])/x';
$a = preg_split($re, $camelCaseString);
return join($a, " " );
}
答案 4 :(得分:10)
虽然ridgerunner的答案很有效,但似乎不适用于出现在句子中间的全帽子串。我使用以下它似乎处理这些就好了:
function splitCamelCase($input)
{
return preg_split(
'/(^[^A-Z]+|[A-Z][^A-Z]+)/',
$input,
-1, /* no limit for replacement count */
PREG_SPLIT_NO_EMPTY /*don't return empty elements*/
| PREG_SPLIT_DELIM_CAPTURE /*don't strip anything from output array*/
);
}
一些测试用例:
assert(splitCamelCase('lowHigh') == ['low', 'High']);
assert(splitCamelCase('WarriorPrincess') == ['Warrior', 'Princess']);
assert(splitCamelCase('SupportSEELE') == ['Support', 'SEELE']);
assert(splitCamelCase('LaunchFLEIAModule') == ['Launch', 'FLEIA', 'Module']);
assert(splitCamelCase('anotherNASATrip') == ['another', 'NASA', 'Trip']);
答案 5 :(得分:6)
$string = preg_replace( '/([a-z0-9])([A-Z])/', "$1 $2", $string );
诀窍是可重复的模式$ 1 $ 2 $ 1 $ 2或更低的UPPERlower UPPERlower等.... 例如 helloWorld = $ 1匹配“hello”,$ 2匹配“W”,$ 1匹配“orld”,所以简而言之你获得$ 1 $ 2 $ 1或“hello World”,将HelloWorld与$ 2 $ 1 $ 2 $ 1或“Hello World”匹配。然后你可以将它们大写成大写第一个单词或在空格上爆炸它们,或者使用_或其他一些字符将它们分开。
简短而简单。
答案 6 :(得分:2)
我带了很酷的Ridgerunner代码(上图)并将其变成了一个函数:
echo deliciousCamelcase('NewNASAModule');
function deliciousCamelcase($str)
{
$formattedStr = '';
$re = '/
(?<=[a-z])
(?=[A-Z])
| (?<=[A-Z])
(?=[A-Z][a-z])
/x';
$a = preg_split($re, $str);
$formattedStr = implode(' ', $a);
return $formattedStr;
}
这将返回:New NASA Module
答案 7 :(得分:1)
另一个选项是匹配/[A-Z]?[a-z]+/
- 如果你知道你的输入是正确的格式,它应该可以很好地工作。
[A-Z]?
将匹配大写字母(或任何内容)。然后[a-z]+
会匹配以下所有小写字母,直到下一场比赛。
答案 8 :(得分:1)
在确定适合您项目的最佳模式时,您需要考虑以下模式因素:
以上因素也恰好是在遵循的层次结构中。换句话说,当1不能完全满足要求时,对2、3或4进行优先级排序对我来说没有多大意义。对我来说,可读性在列表的底部,因为在大多数情况下,我可以遵循语法。
捕获组和环顾四周通常会影响模式效率。事实是,除非您在成千上万的输入字符串上执行此正则表达式,否则就不必为效率而费力。重点可能在于模式的可读性,这可能与模式的简洁性相关。
下面的某些模式将需要通过其preg_
函数进行一些其他处理/标记,但这是根据OP的示例输入进行的一些模式比较:
preg_split()
模式:
/^[^A-Z]+\K|[A-Z][^A-Z]+\K/
(21个步骤)/(^[^A-Z]+|[A-Z][^A-Z]+)/
(26个步骤)/[^A-Z]+\K(?=[A-Z])/
(43个步骤)/(?=[A-Z])/
(50个步骤)/(?=[A-Z]+)/
(50个步骤)/([a-z]{1})[A-Z]{1}/
(53个步骤)/([a-z0-9])([A-Z])/
(68步)/(?<=[a-z])(?=[A-Z])/x
(94个步骤)...为了记录,x
毫无用处。/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/
(134个步骤) preg_match_all()
模式:
/[A-Z]?[a-z]+/
(14个步骤)/((?:^|[A-Z])[a-z]+)/
(35个步骤)我将指出preg_match_all()
和preg_split()
的输出之间有细微的差别。 preg_match_all()
将输出一个二维数组,换句话说,所有全串匹配项都将在[0]
子数组中;如果使用捕获组,则这些子字符串将位于[1]
子数组中。另一方面,preg_split()
仅输出一维数组,因此提供了到所需输出更少的膨胀和更直接的路径。
某些模式不足以处理其中包含ALLCAPS / acronym子字符串的camelCase字符串。如果项目中可能出现这种情况,则仅考虑正确处理这些情况的模式是合乎逻辑的。我不会测试TitleCase输入字符串,因为这离问题太远了。
新的扩展测试字符串电池:
oneTwoThreeFour
hasConsecutiveCAPS
newNASAModule
USAIsGreatAgain
合适的preg_split()
模式:
/[a-z]+\K|(?=[A-Z][a-z]+)/
(149个步骤)*我必须使用[a-z]
进行演示才能正确计数/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/
(547个步骤)合适的preg_match_all()
模式:
/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)/
(75个步骤)最后,我的建议基于我的模式原则/因素层次结构。另外,由于直接关系到所需的输出结构,我建议在preg_split()
上使用preg_match_all()
(尽管这些步骤具有较少的步长)。 (当然,选择您喜欢的任何东西)
代码:(Demo)
$noAcronyms = 'oneTwoThreeFour';
var_export(preg_split('~^[^A-Z]+\K|[A-Z][^A-Z]+\K~', $noAcronyms, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_match_all('~[A-Z]?[^A-Z]+~', $noAcronyms, $out) ? $out[0] : []);
代码:(Demo)
$withAcronyms = 'newNASAModule';
var_export(preg_split('~[^A-Z]+\K|(?=[A-Z][^A-Z]+)~', $withAcronyms, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_match_all('~[A-Z]?[^A-Z]+|[A-Z]+(?=[A-Z][^A-Z]|$)~', $withAcronyms, $out) ? $out[0] : []);
答案 9 :(得分:0)
您可以将“滑行”从小写分割为大写:
$parts = preg_split('/([a-z]{1})[A-Z]{1}/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
//PREG_SPLIT_DELIM_CAPTURE to also return bracketed things
var_dump($parts);
然后,你必须重新构建$ parts
中每对相应项目的单词希望这有帮助
答案 10 :(得分:0)
首先,codaddict感谢你的模式,它帮助了很多!
我需要一个解决方案,以便在介词'a'存在的情况下运行:
e.g。 thisIsACamelcaseSentence。
我找到了两步preg_match的解决方案,并使用了一些选项创建了一个函数:
/*
* input: 'thisIsACamelCaseSentence' output: 'This Is A Camel Case Sentence'
* options $case: 'allUppercase'[default] >> 'This Is A Camel Case Sentence'
* 'allLowerCase' >> 'this is a camel case sentence'
* 'firstUpperCase' >> 'This is a camel case sentence'
* @return: string
*/
function camelCaseToWords($string, $case = null){
isset($case) ? $case = $case : $case = 'allUpperCase';
// Find first occurances of two capitals
preg_match_all('/((?:^|[A-Z])[A-Z]{1})/',$string, $twoCapitals);
// Split them with the 'zzzzzz' string. e.g. 'AZ' turns into 'AzzzzzzZ'
foreach($twoCapitals[0] as $match){
$firstCapital = $match[0];
$lastCapital = $match[1];
$temp = $firstCapital.'zzzzzz'.$lastCapital;
$string = str_replace($match, $temp, $string);
}
// Now split words
preg_match_all('/((?:^|[A-Z])[a-z]+)/', $string, $words);
$output = "";
$i = 0;
foreach($words[0] as $word){
switch($case){
case 'allUpperCase':
$word = ucfirst($word);
break;
case 'allLowerCase':
$word = strtolower($word);
break;
case 'firstUpperCase':
($i == 0) ? $word = ucfirst($word) : $word = strtolower($word);
break;
}
// remove te 'zzzzzz' from a word if it has
$word = str_replace('zzzzzz','', $word);
$output .= $word." ";
$i++;
}
return $output;
}
随意使用它,如果有一个“更容易”的方法一步完成,请评论!
答案 11 :(得分:0)
基于@codaddict答案的完整功能:
function splitCamelCase($str) {
$splitCamelArray = preg_split('/(?=[A-Z])/', $str);
return ucwords(implode($splitCamelArray, ' '));
}