PHP: Najlepszy sposób, aby wyodrębnić tekst w nawiasie?

głosy
57

Jaki jest najlepszy / najbardziej skuteczny sposób, aby wyodrębnić tekst ustawić między nawiasu? Chciałem powiedzieć, aby uzyskać ciąg „tekst” z napisu „Ignoruj ​​wszystko oprócz tego (tekst)” w najbardziej efektywny sposób.

Do tej pory najlepsze jakie wymyślić to:

$fullString = ignore everything except this (text);
$start = strpos('(', $fullString);
$end = strlen($fullString) - strpos(')', $fullString);

$shortString = substr($fullString, $start, $end);

Czy istnieje lepszy sposób to zrobić? Wiem, że na ogół przy użyciu regex wydaje się być mniej efektywne, ale chyba mogę zmniejszyć liczbę wywołań funkcji, może to byłoby najlepsze podejście? Myśli?

Utwórz 13/10/2008 o 03:08
źródło użytkownik
W innych językach...                            


7 odpowiedzi

głosy
100

Chciałbym po prostu zrobić regex i mieć to z głowy. chyba że robią wystarczająco dużo powtórzeń, że staje się ogromny problem z wydajnością, to jest po prostu łatwiejsze do kodu (i zrozumieć, jeśli spojrzeć wstecz na to)

$text = 'ignore everything except this (text)';
preg_match('#\((.*?)\)#', $text, $match);
print $match[1];
Odpowiedział 13/10/2008 o 03:16
źródło użytkownik

głosy
11

Tak, rzeczywiście, kod zostanie zaksięgowana nie działa: substr()'sparametry $ string, $ start i $ długość i strpos()'sparametry $haystack, $needle. Lekko zmieniony:

$ Str = "ignoruj ​​wszystko oprócz tego (tekst)";
$ Start = strpos ($ str, '(');
$ Koniec = strpos ($ str, ')' $ Start + 1);
$ Długość = $ end - $ rozpocząć;
$ Wynik = substr ($ str, $ Start + 1, $ długość - 1);

Niektóre subtelności: Kiedyś $start + 1w offsetu parametru w celu pomocy PHP się podczas wykonywania strpos()wyszukiwania w drugim nawiasie; zwiększamy $startjednego i zmniejszyć $lengthwykluczenie nawiasy z meczu.

Ponadto, nie ma sprawdzania błędów w tym kodzie: będziemy chcieli, aby upewnić się, $starti $endnie === false przed wykonujący substr.

Ponieważ do stosowania strpos/substrw stosunku do wyrażenie regularne wydajność mądry, ten kod pobije wyrażenia regularnego ręce w dół. To trochę wordier chociaż. I jeść i oddychać strpos/substr, więc nie przeszkadza mi to zbyt dużo, ale ktoś może preferować zwartość regex.

Odpowiedział 13/10/2008 o 03:18
źródło użytkownik

głosy
6

Użyć wyrażenia regularnego:

if( preg_match( '!\(([^\)]+)\)!', $text, $match ) )
    $text = $match[1];
Odpowiedział 13/10/2008 o 04:34
źródło użytkownik

głosy
2

Jest to kod próbki wyodrębnienie pomiędzy „[” i] "i przechowywać 2 oddzielne tablice (np tekstu w nawiasach w jeden zespół i tekst poza nawiasach 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 ( "Hello [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"
}
Odpowiedział 29/01/2014 o 09:22
źródło użytkownik

głosy
1

Funkcja ta może być użyteczna.

    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 jest używany, aby znaleźć pozycję pierwszego wystąpieniu w ciąg.

strrpos () =>, który jest używany, aby znaleźć pozycję pierwszego wystąpieniu w ciąg.

Odpowiedział 02/05/2017 o 03:46
źródło użytkownik

głosy
0

Już wysłane rozwiązania regex - \((.*?)\)i \(([^\)]+)\)- nie zwracają najgłębsze struny pomiędzy otwartym i bliskich nawiasach. Jeśli ciąg jest Text (abc(xyz 123)one zarówno powrócić(abc(xyz 123) jako cały mecz, a nie (xyz 123).

Wzór, który pasuje podciągi (stosować z preg_matchsprowadzić pierwszy i preg_match_allpobrać wszystkie wystąpienia) w nawiasie bez innych otwartych i zamkniętych w nawiasach pomiędzy to, że jeśli mecz powinien zawierać nawiasów:

\([^()]*\)

Albo 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 :

  • \( - okrągły otwór wspornika (musi być uciekł do określenia dosłownego nawias, ponieważ znajduje się poza klasą znaków)
  • [^()]*- zero lub więcej znaków innych niż (i )(uwaga nich (i )nie muszą być uciekł wewnątrz klasy znaków, jak w środku, (i )nie mogą być wykorzystane do określenia ugrupowania i są traktowane jako dosłownych nawiasach)
  • \) - zamknięcia rundy wspornika (musi być uciekł do określenia dosłownego nawias, ponieważ znajduje się poza klasą znaków).

\(\KCzęści w alternatywnych dopasowania regex (i pomija z wartości dopasowania (z \Koperatorem zerowania meczu). (?<=\()Jest to pozytywny lookbehind że wymaga (się od razu pojawiają się na lewo od bieżącej lokalizacji, ale (nie jest dodawana do wartości meczu od lookbehind (lookaround) wzory nie są czasochłonne. (?=\()Jest to pozytywny uprzedzona, że wymaga )char natychmiast pojawiają się na prawo od 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
}

Wydajność:

Array ( [0] => (text)  [1] => (text here) )
Array ( [0] => text    [1] => text here   )
Odpowiedział 13/05/2019 o 17:08
źródło użytkownik

głosy
0
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 niewielka poprawa w poprzedniej odpowiedzi, że zwróci wszystkie wzory w postaci tablicy:

getStringsBetween ( '[t] [] jest [test] string [wzór]') zwróci:

Odpowiedział 08/04/2019 o 08:21
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more