Jaki jest najlepszy / najskuteczniejszy sposób wyodrębnienia tekstu umieszczonego w nawiasach? Powiedzmy, że chciałem uzyskać ciąg „tekst” z ciągu „ignoruj wszystko oprócz tego (tekstu)” w najbardziej efektywny sposób.
Jak dotąd najlepsze, co wymyśliłem, to:
$fullString = "ignore everything except this (text)";
$start = strpos('(', $fullString);
$end = strlen($fullString) - strpos(')', $fullString);
$shortString = substr($fullString, $start, $end);
Czy jest lepszy sposób, aby to zrobić? Wiem, że generalnie używanie wyrażeń regularnych jest mniej wydajne, ale jeśli nie uda mi się zmniejszyć liczby wywołań funkcji, być może byłoby to najlepsze podejście? Myśli?
s($fullString)->between("(", ")")
pomocny, co znajdziesz w tej samodzielnej bibliotece .Odpowiedzi:
po prostu zrobiłbym regex i skończył z tym. chyba że wykonujesz wystarczającą liczbę iteracji, które stają się ogromnym problemem z wydajnością, po prostu łatwiej jest kodować (i zrozumieć, gdy spojrzysz wstecz)
$text = 'ignore everything except this (text)'; preg_match('#\((.*?)\)#', $text, $match); print $match[1];
źródło
Tak, rzeczywiście, kod zostanie zaksięgowana nie działa:
substr()'s
parametry $ string, $ start i $ długość istrpos()'s
parametry$haystack
,$needle
. Lekko zmieniony:Kilka subtelności: użyłem
$start + 1
parametru offset, aby pomóc PHP podczasstrpos()
wyszukiwania w drugim nawiasie; zwiększamy$start
jeden i zmniejszamy,$length
aby wykluczyć nawiasy z dopasowania.Ponadto nie ma sprawdzania błędów w tym kodzie: będziesz chciał się upewnić
$start
i$end
nie === false przed wykonaniemsubstr
.Jeśli chodzi o używanie w
strpos/substr
porównaniu do wyrażenia regularnego; pod względem wydajności kod ten bez trudu pokonuje wyrażenie regularne. Jest jednak trochę bardziej wyrazisty. Jem i oddychamstrpos/substr
, więc nie przeszkadza mi to zbytnio, ale ktoś inny może preferować zwartość wyrażenia regularnego.źródło
Użyj wyrażenia regularnego:
if( preg_match( '!\(([^\)]+)\)!', $text, $match ) ) $text = $match[1];
źródło
To jest przykładowy kod do wyodrębnienia całego tekstu między „[” a „]” i zapisania go w 2 oddzielnych tablicach (tj. Tekst w nawiasach w jednej tablicy i tekst poza nawiasami w innej tablicy)
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); }
Wyjście: extract_text ("cześć, jak się masz?"); będzie produkować:
array(1) { [0]=> string(18) "hello how are you?" } array(0) { }
extract_text ("cześć [http://www.google.com/test.mp3] jak się masz?"); będzie produkować
array(2) { [0]=> string(6) "hello " [1]=> string(13) " how are you?" } array(1) { [0]=> string(30) "http://www.google.com/test.mp3" }
źródło
Ta funkcja może być przydatna.
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 () =>, który służy do znalezienia pozycji pierwszego wystąpienia w ciągu.
strrpos () =>, który służy do znalezienia pozycji pierwszego wystąpienia w ciągu.
źródło
Już opublikowane rozwiązania regex -
\((.*?)\)
i\(([^\)]+)\)
- nie zwracają najbardziej wewnętrznych ciągów między nawiasami otwierającymi i zamykającymi. Jeśli ciąg jestText (abc(xyz 123)
one zarówno powrócić(abc(xyz 123)
jako cały mecz, a nie(xyz 123)
.Wzorzec pasujący do podciągów (użyj z,
preg_match
aby pobrać pierwszy ipreg_match_all
wszystkie wystąpienia) w nawiasach bez innych otwierających i zamykających nawiasów między nimi to, jeśli dopasowanie powinno zawierać nawiasy:Lub chcesz uzyskać wartości bez nawiasów:
\(([^()]*)\) // 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
Wymień
*
się+
jeśli nie musi wynosić co najmniej 1 char pomiędzy(
i)
.Szczegóły :
\(
- otwierający nawias okrągły (musi zostać zmieniony, aby wskazać literalny nawias, ponieważ jest używany poza klasą znaków)[^()]*
- zero lub więcej znaków innych niż(
i)
(zwróć uwagę na te(
i)
nie muszą być znakami ucieczki wewnątrz klasy znaków, tak jak w niej,(
i)
nie można ich użyć do określenia grupowania i są traktowane jako dosłowne nawiasy)\)
- zamykający nawias okrągły (musi zostać zmieniony, aby wskazać literalny nawias, ponieważ jest używany poza klasą znaków).\(\K
Części w alternatywnych dopasowania regex(
i pomija z wartości dopasowania (z\K
operatorem zerowania meczu).(?<=\()
to pozytywne spojrzenie w tył, które wymaga(
natychmiastowego pojawienia się po lewej stronie bieżącej lokalizacji, ale(
nie jest dodawany do wartości dopasowania, ponieważ wzorce lookbehind (patrzenie w tył) nie są używane.(?=\()
to pozytywne spojrzenie w przód, które wymaga)
natychmiastowego pojawienia się znaku po prawej stronie bieżącej lokalizacji.Kod PHP :
$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 }
Wynik:
Array ( [0] => (text) [1] => (text here) ) Array ( [0] => text [1] => text here )
źródło
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; }
jest to małe ulepszenie poprzedniej odpowiedzi, która zwróci wszystkie wzorce w postaci tablicy:
getStringsBetween ('[T] his [] is [test] string [pattern]') zwróci:
źródło
Myślę, że to najszybszy sposób na umieszczenie słów między pierwszym nawiasem w ciągu.
$string = 'ignore everything except this (text)'; $string = explode(')', (explode('(', $string)[1]))[0]; echo $string;
źródło