Wie würde ich das Wort teilen?
oneTwoThreeFour
in ein Array, damit ich bekommen kann:
one Two Three Four
mit preg_match
?
Ich habe es müde, aber es gibt nur das ganze Wort
$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)`;
Sie können auch preg_match_all
verwenden als:
preg_match_all('/((?:^|[A-Z])[a-z]+)/',$str,$matches);
Erläuterung:
( - 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.
Sie können preg_split
verwenden als:
$arr = preg_split('/(?=[A-Z])/',$str);
Ich teile die Eingabezeichenfolge vor dem Großbuchstaben auf. Der verwendete Ausdruck (?=[A-Z])
stimmt mit dem Punkt vor einem Großbuchstaben überein.
Ich weiß, dass dies eine alte Frage mit einer akzeptierten Antwort ist, aber IMHO gibt es eine bessere Lösung:
<?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]);
}
?>
Beachten Sie, dass dieser Regex (wie die '/(?=[A-Z])/'
-Lösung von codaddict - die wie ein Zauber für wohlgeformte camelCase-Wörter wirkt) nur eine position innerhalb des Strings entspricht und keinerlei Text verbraucht. Diese Lösung hat den zusätzlichen Vorteil, dass sie auch für nicht so gut geformte Pseudo-Camelcase-Wörter wie StartsWithCap
und: hasConsecutiveCAPS
korrekt funktioniert.
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"
Bearbeitet: 2014-04-12: Geänderte Regex-, Skript- und Testdaten, um den Fall "NewNASAModule"
richtig zu teilen (als Antwort auf den Kommentar von rr).
Eine funktionalisierte Version der Antwort von @ 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, " " );
}
Die Antwort von ridgerunner funktioniert zwar großartig, scheint aber nicht mit Großbuchstaben zu funktionieren, die in der Satzmitte erscheinen. Ich benutze folgendes und es scheint damit klar zu gehen:
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*/
);
}
Einige Testfälle:
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 );
Der Trick ist ein wiederholbares Muster von $ 1 $ 2 $ 1 $ 2 oder niedriger UPPERlower UPPERlower etc .... Zum Beispiel HelloWorld = $ 1 entspricht "hallo", "2" entspricht "W" und "1" entspricht "orld" Sie erhalten $ 1 $ 2 $ 1 oder "Hallo Welt", entspricht HelloWorld als $ 2 $ 1 $ 2 $ 1 oder wieder "Hello World". Dann können Sie das erste Word in Großbuchstaben schreiben oder auf dem Feld explodieren oder ein _ oder ein anderes Zeichen verwenden, um sie voneinander zu trennen.
Kurz und einfach.
Ich habe den Code von cooler Ridgerunner (oben) genommen und eine Funktion erstellt:
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;
}
Dies wird zurückgegeben: New NASA Module
Bei der Ermittlung des besten Musters für Ihr Projekt müssen Sie die folgenden Musterfaktoren berücksichtigen:
Die oben genannten Faktoren liegen zufällig auch in der hierarchischen Reihenfolge, die danach strebt, zu gehorchen. Mit anderen Worten, es macht für mich wenig Sinn, 2, 3 oder 4 zu priorisieren, wenn 1 die Anforderungen nicht ganz erfüllt. Die Lesbarkeit steht für mich am Ende der Liste, da ich in den meisten Fällen der Syntax folgen kann.
Erfassungsgruppen und Lookarounds wirken sich häufig auf die Mustereffizienz aus. Die Wahrheit ist, es sei denn, Sie führen diesen regulären Ausdruck mit Tausenden von Eingabezeichenfolgen aus, besteht keine Notwendigkeit, über die Effizienz zu streiten. Es ist vielleicht wichtiger, sich auf die Musterlesbarkeit zu konzentrieren, die mit der Musterkürze in Verbindung gebracht werden kann.
Einige der folgenden Muster erfordern eine zusätzliche Behandlung/Kennzeichnung durch ihre preg_
-Funktion, aber hier sind einige Mustervergleiche, die auf der Beispieleingabe des OP basieren:
preg_split()
patterns:
/^[^A-Z]+\K|[A-Z][^A-Z]+\K/
(21 Schritte)/(^[^A-Z]+|[A-Z][^A-Z]+)/
(26 Schritte)/[^A-Z]+\K(?=[A-Z])/
(43 Schritte)/(?=[A-Z])/
(50 Schritte)/(?=[A-Z]+)/
(50 Schritte)/([a-z]{1})[A-Z]{1}/
(53 Schritte)/([a-z0-9])([A-Z])/
(68 Schritte)/(?<=[a-z])(?=[A-Z])/x
(94 Schritte) ... für den Datensatz ist die x
unbrauchbar./(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/
(134 Schritte)preg_match_all()
patterns:
/[A-Z]?[a-z]+/
(14 Schritte)/((?:^|[A-Z])[a-z]+)/
(35 Schritte)Ich werde darauf hinweisen, dass es einen subtilen Unterschied zwischen der Ausgabe von preg_match_all()
und preg_split()
gibt. preg_match_all()
gibt ein zweidimensionales Array aus, mit anderen Worten, alle Übereinstimmungen mit der vollständigen Zeichenfolge befinden sich im Unterarray [0]
. Wenn eine Erfassungsgruppe verwendet wird, befinden sich diese Teilzeichenfolgen im Unterfeld [1]
. Andererseits gibt preg_split()
nur ein eindimensionales Array aus und bietet daher einen weniger aufgeblähten und direkteren Pfad zur gewünschten Ausgabe.
Einige der Muster sind nicht ausreichend, wenn es sich um camelCase-Zeichenfolgen handelt, die eine ALLCAPS/acronym-Teilzeichenfolge enthalten. Wenn dies ein Randfall ist, der in Ihrem Projekt möglich ist, ist es logisch, nur Muster zu berücksichtigen, die diese Fälle korrekt behandeln. Ich werde keine TitleCase-Eingabezeichenfolgen testen, da dies zu weit von der Frage entfernt ist.
Neue, erweiterte Batterie mit Teststrings:
oneTwoThreeFour
hasConsecutiveCAPS
newNASAModule
USAIsGreatAgain
Geeignete preg_split()
-Muster:
/[a-z]+\K|(?=[A-Z][a-z]+)/
(149 Schritte) * Ich musste [a-z]
verwenden, damit die Demo richtig zählt/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/
(547 Schritte)Geeignet preg_match_all()
muster:
/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)/
(75 Schritte)Schließlich meine Empfehlungen auf der Grundlage meiner Musterprinzipien/Faktorhierarchie. Außerdem empfehle ich preg_split()
gegenüber preg_match_all()
(trotz der Muster mit weniger Schritten), um die gewünschte Ausgabestruktur direkt zu erreichen. (natürlich, wähle was du willst)
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] : []);
Eine andere Option ist das Abgleichen von /[A-Z]?[a-z]+/
. Wenn Sie wissen, dass Ihre Eingabe das richtige Format hat, sollte es gut funktionieren.
[A-Z]?
würde mit einem Großbuchstaben (oder nichts) übereinstimmen. [a-z]+
würde dann bis zum nächsten Buchstaben mit allen folgenden Kleinbuchstaben übereinstimmen.
Arbeitsbeispiel: https://regex101.com/r/kNZfEI/1
Volle Funktion basierend auf @codaddict Antwort:
function splitCamelCase($str) {
$splitCamelArray = preg_split('/(?=[A-Z])/', $str);
return ucwords(implode($splitCamelArray, ' '));
}
Vielleicht kann Ihnen meine Frage helfen. Ich habe gestern dasselbe gefragt, aber über Java
Sie können bei einem "Gleiten" von Kleinbuchstaben zu Großbuchstaben aufteilen, also:
$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);
Ärgerlicherweise müssen Sie dann die Wörter aus jedem entsprechenden Elementpaar in $ parts neu erstellen
Hoffe das hilft
Zunächst einmal danke ich dir für dein Muster, es hat sehr geholfen!
Ich brauchte eine Lösung, die funktioniert, wenn eine Präposition 'a' existiert:
z.B. thisIsACamelcaseSentence.
Ich habe die Lösung in einem zweistufigen preg_match gefunden und eine Funktion mit einigen Optionen erstellt:
/*
* 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;
}
Fühlen Sie sich frei, es zu benutzen, und falls es eine "einfachere" Möglichkeit gibt, dies in einem Schritt zu tun, kommentieren Sie bitte!