Was ist der beste / effizienteste Weg, um Textsätze in Klammern zu extrahieren? Angenommen, ich wollte die Zeichenfolge "Text" aus der Zeichenfolge "Alles außer diesem (Text) ignorieren" so effizient wie möglich erhalten.
Das Beste, was ich mir bisher ausgedacht habe, ist Folgendes:
$fullString = "ignore everything except this (text)";
$start = strpos('(', $fullString);
$end = strlen($fullString) - strpos(')', $fullString);
$shortString = substr($fullString, $start, $end);
Gibt es einen besseren Weg, dies zu tun? Ich weiß, dass die Verwendung von Regex im Allgemeinen weniger effizient ist. Wenn ich jedoch die Anzahl der Funktionsaufrufe nicht reduzieren kann, ist dies möglicherweise der beste Ansatz. Gedanken?
s($fullString)->between("(", ")")
hilfreiche Informationen in dieser eigenständigen Bibliothek .Antworten:
Ich würde einfach eine Regex machen und es hinter mich bringen. Wenn Sie nicht genügend Iterationen ausführen, um ein großes Leistungsproblem zu lösen, ist es einfacher, Code zu erstellen (und zu verstehen, wenn Sie darauf zurückblicken).
$text = 'ignore everything except this (text)'; preg_match('#\((.*?)\)#', $text, $match); print $match[1];
quelle
Der von Ihnen veröffentlichte Code funktioniert also nicht: Die
substr()'s
Parameter sind $ string, $ start und $ length und diestrpos()'s
Parameter sind$haystack
,$needle
. Leicht verändert:Einige Feinheiten: Ich habe
$start + 1
den Offset-Parameter verwendet, um PHP bei derstrpos()
Suche in der zweiten Klammer zu unterstützen. Wir erhöhen$start
eins und reduzieren$length
, um die Klammern von der Übereinstimmung auszuschließen.Außerdem gibt es in diesem Code keine Fehlerprüfung: Sie sollten sicherstellen
$start
und$end
nicht === false, bevor Sie das ausführensubstr
.Wie für die Verwendung
strpos/substr
gegen Regex; In Bezug auf die Leistung schlägt dieser Code einen regulären Ausdruck zweifellos. Es ist allerdings etwas wortreicher. Ich esse und atmestrpos/substr
, deshalb stört mich das nicht allzu sehr, aber jemand anderes mag die Kompaktheit eines regulären Ausdrucks bevorzugen.quelle
Verwenden Sie einen regulären Ausdruck:
if( preg_match( '!\(([^\)]+)\)!', $text, $match ) ) $text = $match[1];
quelle
Dies ist ein Beispielcode, um den gesamten Text zwischen '[' und ']' zu extrahieren und in 2 separaten Arrays zu speichern (dh Text in Klammern in einem Array und Text außerhalb von Klammern in einem anderen Array).
function extract_text($string) { $text_outside=array(); $text_inside=array(); $t=""; for($i=0;$i<strlen($string);$i++) { if($string[$i]=='[') { $text_outside[]=$t; $t=""; $t1=""; $i++; while($string[$i]!=']') { $t1.=$string[$i]; $i++; } $text_inside[] = $t1; } else { if($string[$i]!=']') $t.=$string[$i]; else { continue; } } } if($t!="") $text_outside[]=$t; var_dump($text_outside); echo "\n\n"; var_dump($text_inside); }
Ausgabe: extract_text ("Hallo, wie geht es dir?"); wird herstellen:
array(1) { [0]=> string(18) "hello how are you?" } array(0) { }
extract_text ("Hallo [http://www.google.com/test.mp3] wie geht es dir?"); wird herstellen
array(2) { [0]=> string(6) "hello " [1]=> string(13) " how are you?" } array(1) { [0]=> string(30) "http://www.google.com/test.mp3" }
quelle
Diese Funktion kann nützlich sein.
public static function getStringBetween($str,$from,$to, $withFromAndTo = false) { $sub = substr($str, strpos($str,$from)+strlen($from),strlen($str)); if ($withFromAndTo) return $from . substr($sub,0, strrpos($sub,$to)) . $to; else return substr($sub,0, strrpos($sub,$to)); } $inputString = "ignore everything except this (text)"; $outputString = getStringBetween($inputString, '(', ')')); echo $outputString; //output will be test $outputString = getStringBetween($inputString, '(', ')', true)); echo $outputString; //output will be (test)
strpos () =>, mit dem die Position des ersten Auftretens in einem String ermittelt wird.
strrpos () =>, mit dem die Position des ersten Auftretens in einem String ermittelt wird.
quelle
Die bereits veröffentlichten Regex-Lösungen -
\((.*?)\)
und\(([^\)]+)\)
- geben nicht die innersten Zeichenfolgen zwischen einer offenen und einer geschlossenen Klammer zurück. Wenn ein String istText (abc(xyz 123)
sie beide zurückgeben ein(abc(xyz 123)
als Ganzes Spiel, und nicht(xyz 123)
.Das Muster, das Teilzeichenfolgen (
preg_match
zum Abrufen der ersten undpreg_match_all
zum Abrufen aller Vorkommen mit) in Klammern ohne andere offene und geschlossene Klammern dazwischen entspricht, lautet, wenn die Übereinstimmung Klammern enthalten soll:Oder Sie möchten Werte ohne Klammern erhalten:
\(([^()]*)\) // get Group 1 values after a successful call to preg_match_all, see code below \(\K[^()]*(?=\)) // this and the one below get the values without parentheses as whole matches (?<=\()[^()]*(?=\)) // less efficient, not recommended
Ersetzen Sie
*
durch,+
wenn zwischen(
und mindestens 1 Zeichen liegen muss)
.Details :
\(
- eine öffnende runde Klammer (muss maskiert werden, um eine wörtliche Klammer zu kennzeichnen, da sie außerhalb einer Zeichenklasse verwendet wird)[^()]*
- null oder mehr Zeichen , die nicht(
und)
(beachten Sie diese(
und)
müssen nicht als im Inneren innerhalb einer Zeichenklasse entronnen sein,(
und)
nicht verwendet werden kann , eine Gruppierung und werden behandelt , als wörtliche Klammern angeben)\)
- eine schließende runde Klammer (muss maskiert werden, um eine wörtliche Klammer zu kennzeichnen, da sie außerhalb einer Zeichenklasse verwendet wird).Der
\(\K
Teil in einem alternativen regulären Ausdruck stimmt(
mit dem\K
Übereinstimmungswert überein und lässt ihn aus (mit dem Operator zum Zurücksetzen der Übereinstimmung).(?<=\()
ist ein positives Lookbehind, bei dem a(
unmittelbar links vom aktuellen Speicherort angezeigt werden muss , das(
jedoch nicht zum Übereinstimmungswert hinzugefügt wird, da Lookbehind-Muster (Lookaround-Muster) nicht verbraucht werden.(?=\()
ist ein positiver Lookahead, für den ein)
Zeichen unmittelbar rechts vom aktuellen Standort angezeigt werden muss .PHP-Code :
$fullString = 'ignore everything except this (text) and (that (text here))'; if (preg_match_all('~\(([^()]*)\)~', $fullString, $matches)) { print_r($matches[0]); // Get whole match values print_r($matches[1]); // Get Group 1 values }
Ausgabe:
Array ( [0] => (text) [1] => (text here) ) Array ( [0] => text [1] => text here )
quelle
function getStringsBetween($str, $start='[', $end=']', $with_from_to=true){ $arr = []; $last_pos = 0; $last_pos = strpos($str, $start, $last_pos); while ($last_pos !== false) { $t = strpos($str, $end, $last_pos); $arr[] = ($with_from_to ? $start : '').substr($str, $last_pos + 1, $t - $last_pos - 1).($with_from_to ? $end : ''); $last_pos = strpos($str, $start, $last_pos+1); } return $arr; }
Dies ist eine kleine Verbesserung gegenüber der vorherigen Antwort, bei der alle Muster in Array-Form zurückgegeben werden:
getStringsBetween ('[T] his [] is [test] string [pattern]') gibt Folgendes zurück:
quelle
Ich denke, dies ist der schnellste Weg, um die Wörter zwischen den ersten Klammern in einer Zeichenfolge zu erhalten.
$string = 'ignore everything except this (text)'; $string = explode(')', (explode('(', $string)[1]))[0]; echo $string;
quelle