PHP: Найкращий спосіб витягти текст у дужках?


83

Який найкращий / найефективніший спосіб виділити набір тексту між дужками? Скажімо, я хотів отримати рядок "text" із рядка "ігнорувати все, крім цього (text)" найбільш ефективним способом.

Поки що найкраще, що я придумав, це:

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

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

Чи є кращий спосіб це зробити? Я знаю, що загалом використання регулярного виразу є менш ефективним, але якщо я не можу зменшити кількість викликів функцій, можливо, це був би найкращий підхід? Думки?


Ви можете виявити s($fullString)->between("(", ")")корисним, як це знайдено в цій автономній бібліотеці .
caw

Відповіді:


144

я б просто зробив регулярний вираз і закінчив би з цим. якщо ви не робите достатньо ітерацій, щоб це стало величезною проблемою продуктивності, просто простіше кодувати (і зрозуміти, коли ви оглянетеся назад)

$text = 'ignore everything except this (text)';
preg_match('#\((.*?)\)#', $text, $match);
print $match[1];

1
Ні, це не так:. відповідає лише одному символу.
Едвард З. Ян

1
не обов'язково, ? ледачий матч. без нього, рядок типу "ігнорувати (все), крім цього (текст)", збіг в кінцевому підсумку буде "вічним", крім цього (текст "
Оуен,

1
Добре знати. Слід уникати всіх цих квадратів не. Наприклад / src = "([^"] *) "/ тепер замінено на /src="(.*?)"/: D
Димитрій,

Добре, що ви можете "зрозуміти, коли озирнетесь на це". Якщо цього не вдасться, у вас є кілька коментарів щодо переповнення стека, щоб це пояснити.
Mnebuerquo

2
/ src = "([^"] *) "/ ефективніший, ніж /src="(.*?)"/
Тань,

14

Так, власне, код розміщений не працює: substr()'sпараметри $ рядок, $ початку і $ довжина і strpos()'sпараметри $haystack, $needle. Трохи змінено:

$ str = "ігнорувати все, крім цього (тексту)";
$ start = strpos ($ str, '(');
$ end = strpos ($ str, ')', $ start + 1);
$ length = $ end - $ start;
$ result = substr ($ str, $ start + 1, $ length - 1);

Деякі тонкощі: я використав $start + 1параметр offset, щоб допомогти PHP вийти під час strpos()пошуку в другій дужці; ми збільшуємо $startодиницю і зменшуємо, $lengthщоб виключити дужки з відповідності.

Крім того, у цьому коді немає перевірки помилок: ви хочете переконатись $startі $endне === false перед виконанням substr.

Що стосується використання strpos/substrпроти регулярного виразу; з точки зору продуктивності, цей код буде перевершувати регулярний вираз. Хоча це трохи поважніше. Я їм і дихаю strpos/substr, тому я не надто проти цього, але хтось інший може віддати перевагу компактності регулярного виразу.


9

Використовуйте регулярний вираз:

if( preg_match( '!\(([^\)]+)\)!', $text, $match ) )
    $text = $match[1];

3

Це зразок коду для вилучення всього тексту між '[' та ']' та збереження його у 2 окремих масивах (тобто текст всередині дужок в одному масиві та текст поза дужками в іншому масиві)

   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);
  }

Вихідні дані: extract_text ("привіт, як справи?"); буде виробляти:

array(1) {
  [0]=>
  string(18) "hello how are you?"
}

array(0) {
}

extract_text ("привіт [http://www.google.com/test.mp3] як справи?"); буде виробляти

array(2) {
  [0]=>
  string(6) "hello "
  [1]=>
  string(13) " how are you?"
}


array(1) {
  [0]=>
  string(30) "http://www.google.com/test.mp3"
}

+1, але як зробити те саме для [* та *]? Оскільки [], можливо, використовується лише в html, наприклад.
Mike Castro Demaria

1

Ця функція може бути корисною.

    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 () =>, який використовується для пошуку позиції першої зустрічі в рядку.

strrpos () =>, який використовується для пошуку позиції першої зустрічі в рядку.


1

Вже опубліковані рішення регулярних виразів - \((.*?)\)і \(([^\)]+)\)- не повертають внутрішніх рядків між відкритою та закритою дужками. Якщо рядок є, Text (abc(xyz 123)вони обидва повертають a (abc(xyz 123)як цілий збіг, а ні (xyz 123).

Шаблон, який відповідає підрядкам (використовуйте preg_matchдля отримання першого та preg_match_allотримання всіх випадків) у дужках без інших відкритих та закритих дужок між ними, якщо відповідність повинна включати дужки:

\([^()]*\)

Або ви хочете отримати значення без дужок:

\(([^()]*)\)        // 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

Замініть *на, +якщо між (і повинен бути принаймні 1 символ ).

Подробиці :

  • \( - відкриваюча кругла дужка (має бути екранованою для позначення буквальної дужки, оскільки вона використовується поза класом символів)
  • [^()]*- нуль або більше символів , крім (і )(зверніть увагу , це (і )не повинні бути екрановані всередині класу символів , як всередині нього, (і )не може бути використаний для вказівки групування і розглядаються в якості буквальних дужках)
  • \) - закриваюча кругла дужка (її потрібно вимкнути для позначення буквальної дужки, оскільки вона використовується поза класом символів).

\(\KУчасть в альтернативних матчах регулярних виразів (і опускають від значення матчу (з \Kоператором скидання матчу). (?<=\()є позитивним оглядом позаду, який вимагає, щоб a (з'явився відразу зліва від поточного розташування, але (не додається до значення збігу, оскільки шаблони огляду (lookaround) не споживають. (?=\()є позитивним результатом пошуку, який вимагає появи )символу відразу праворуч від поточного місця.

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
}

Вихід:

Array ( [0] => (text)  [1] => (text here) )
Array ( [0] => text    [1] => text here   )

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; }

це невелике покращення попередньої відповіді, яка поверне всі шаблони у вигляді масиву:

getStringsBetween ('[T] his [] is [test] string [pattern]') поверне:


0

я думаю, це найшвидший спосіб отримати слова між першими дужками в рядку.

$string = 'ignore everything except this (text)';
$string = explode(')', (explode('(', $string)[1]))[0];
echo $string;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.