CamelCase 단어를 PHP preg_match (정규식)를 사용하여 단어로 분할
단어를 나누는 방법은 다음과 같습니다.
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)`;
다음 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.
다음 preg_split과 같이 사용할 수 있습니다 .
$arr = preg_split('/(?=[A-Z])/',$str);
기본적으로 대문자 바로 전에 입력 문자열을 분할하고 있습니다. 사용 된 정규식 (?=[A-Z])은 대문자 바로 앞의 지점과 일치합니다.
나는 이것이 받아 들여지는 대답이있는 오래된 질문이라는 것을 알고 있지만 IMHO에는 더 나은 해결책이 있습니다.
<?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]);
}
?>
이 정규식은 ( '/(?=[A-Z])/'잘 형성된 camelCase 단어의 매력처럼 작동하는 codaddict의 솔루션과 같이) 문자열 내의 위치 만 일치 하고 텍스트를 전혀 사용하지 않습니다. 이 솔루션은 다음과 같이 잘 구성되지 않은 유사 낙타 단어에도 올바르게 작동한다는 추가 이점이 있습니다. 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의 의견에 대한 응답).
@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, " " );
}
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']);
$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"와 일치시킵니다. 그런 다음 첫 번째 단어를 대문자로 소문자로 바꾸거나 공백에서 폭발 시키거나 _ 또는 다른 문자를 사용하여 분리 할 수 있습니다.
짧고 간단합니다.
나는 멋진 사람 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
또 다른 옵션은 매칭입니다. /[A-Z]?[a-z]+/입력 한 형식이 올바른지 알고 있다면 잘 작동합니다.
[A-Z]?대문자 (또는 아무것도 일치하지 않음)와 일치합니다. [a-z]+그런 다음 다음 일치까지 다음 모든 소문자와 일치합니다.
실례 : https://regex101.com/r/kNZfEI/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 단계)
I'll point out that there is a subtle difference between the output of preg_match_all() and preg_split(). preg_match_all() will output a 2-dimensional array, in other words, all of the fullstring matches will be in the [0] subarray; if there is a capture group used, those substrings will be in the [1] subarray. On the other hand, preg_split() only outputs a 1-dimensional array and therefore provides a less bloated and more direct path to the desired output.
Some of the patterns are insufficient when dealing with camelCase strings that contain an ALLCAPS/acronym substring in them. If this is a fringe case that is possible within your project, it is logical to only consider patterns that handle these cases correctly. I will not be testing TitleCase input strings because that is creeping too far from the question.
New Extended Battery of Test Strings:
oneTwoThreeFour
hasConsecutiveCAPS
newNASAModule
USAIsGreatAgain
Suitable preg_split() patterns:
/[a-z]+\K|(?=[A-Z][a-z]+)/(149 steps) *I had to use[a-z]for the demo to count properly/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/(547 steps)
Suitable preg_match_all() pattern:
/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)/(75 steps)
Finally, my recommendations based on my pattern principles / factor hierarchy. Also, I recommend preg_split() over preg_match_all() (despite the patterns having less steps) as a matter of directness to the desired output structure. (of course, choose whatever you like)
Code: (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] : []);
Code: (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] : []);
You can split on a "glide" from lowercase to uppercase thus:
$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);
Annoyingly you will then have to rebuild the words from each corresponding pair of items in $parts
Hope this helps
First of all codaddict thank you for your pattern, it helped a lot!
I needed a solution that works in case a preposition 'a' exists:
e.g. thisIsACamelcaseSentence.
I found the solution in doing a two step preg_match and made a function with some options:
/*
* 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;
}
Feel free to use it, and in case there is an 'easier' way to do this in one step please comment!
Full function based on @codaddict answer:
function splitCamelCase($str) {
$splitCamelArray = preg_split('/(?=[A-Z])/', $str);
return ucwords(implode($splitCamelArray, ' '));
}
'Program Club' 카테고리의 다른 글
| Core Data 다중 스레드 애플리케이션 (0) | 2020.11.25 |
|---|---|
| 치명적인 오류 : 정의되지 않은 함수 mcrypt_encrypt () 호출 (0) | 2020.11.25 |
| ios facebook sdk 4.0 로그인 오류 코드 304 (0) | 2020.11.25 |
| 파이썬에서 두 개의 n 차원 벡터 사이의 각도 (0) | 2020.11.25 |
| 신속하게 문자열에서 숫자가 아닌 모든 문자를 제거하십시오. (0) | 2020.11.25 |