Какой лучший / самый эффективный способ извлечь текст, заключенный в круглые скобки? Скажем, я хотел получить строку «текст» из строки «игнорировать все, кроме этого (текста)» наиболее эффективным способом.
Пока что лучшее, что я придумал, это следующее:
$fullString = "ignore everything except this (text)";
$start = strpos('(', $fullString);
$end = strlen($fullString) - strpos(')', $fullString);
$shortString = substr($fullString, $start, $end);
Есть лучший способ сделать это? Я знаю, что в целом использование регулярных выражений имеет тенденцию быть менее эффективным, но если я не могу уменьшить количество вызовов функций, возможно, это будет лучший подход? Мысли?






Я бы просто сделал регулярное выражение и покончил с этим. если вы не делаете достаточно итераций, чтобы это стало огромной проблемой для производительности, просто кодировать проще (и понять, когда вы оглянетесь на это)
$text = 'ignore everything except this (text)';
preg_match('#\((.*?)\)#', $text, $match);
print $match[1];
Нет, это не так:. соответствует только одному символу.
не обязательно, ? ленивый матч. без него строка вроде 'ignore (all) except this (text)', совпадение закончится как 'everthing), кроме этого (текст'
Хорошо знать. Следует избегать всех этих квадратов. Например. / src = "([^"] *) "/ теперь заменено на /src="(.*?)"/: D
Хорошо, что можно «понять, оглянувшись на это». В противном случае у вас есть несколько комментариев о переполнении стека, чтобы прояснить это.
/ src = "([^"] *) "/ более эффективен, чем /src="(.*?)"/
Я. квадрат не есть, причина в том? заставляет двигатель сильно откатываться назад, что очень дорого. квадратные знаки будут соответствовать "форварду" в этом смысле. я предпочитаю? обозначения, так что если производительность не является проблемой, я становлюсь ленивым :)
Если я хочу кроме (текста), тогда?
Итак, на самом деле, опубликованный вами код не работает: параметры substr()'s - это $ string, $ start и длина $, а параметры strpos()'s - это $haystack, $needle. Немного изменено:
$str = "ignore everything except this (text)";
$start = strpos($str, '(');
$end = strpos($str, ')', $start + 1);
$length = $end - $start;
$result = substr($str, $start + 1, $length - 1);Некоторые тонкости: я использовал $start + 1 в параметре смещения, чтобы помочь PHP при поиске strpos() во второй скобке; мы увеличиваем $start на единицу и уменьшаем $length, чтобы исключить скобки из совпадения.
Кроме того, в этом коде нет проверки ошибок: вам нужно убедиться, что $start и $end не имеют === false перед выполнением substr.
Что касается использования strpos/substr по сравнению с регулярным выражением; с точки зрения производительности этот код превзойдет регулярное выражение. Хотя это немного многословнее. Я ем и дышу strpos/substr, поэтому я не особо возражаю против этого, но кто-то другой может предпочесть компактность регулярного выражения.
Обратите внимание, что если вы измените этот код, чтобы использовать strrpos (начинается с конца строки) в конце $, тогда он будет правильно обрабатывать случаи, когда внутри ... как скобки есть скобки (ну, это (очень) хорошо).
Используйте регулярное выражение:
if ( preg_match( '!\(([^\)]+)\)!', $text, $match ) )
$text = $match[1];
Это пример кода для извлечения всего текста между '[' и ']' и сохранения его в двух отдельных массивах (т.е. текст внутри скобок в одном массиве и текст вне скобок в другом массиве)
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.
Эта функция может быть полезной.
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 () =>, который используется для поиска позиции первого появления в строке.
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]') вернет:
Уже опубликованные решения с регулярными выражениями - \((.*?)\) и \(([^\)]+)\) - не возвращают строки сокровенный между открытыми и закрытыми скобками. Если строка - Text (abc(xyz 123), они и то и другоевозвращаться соответствуют (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). (?<=\() - это положительный просмотр назад, который требует, чтобы ( появлялся сразу слева от текущего местоположения, но ( не добавляется к значению соответствия, поскольку шаблоны просмотра назад (lookaround) не используются. (?=\() - это положительный просмотр вперед, который требует, чтобы символ ) появлялся сразу же справа от текущего местоположения.
$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 )
я думаю, что это самый быстрый способ получить слова между первой круглой скобкой в строке.
$string = 'ignore everything except this (text)';
$string = explode(')', (explode('(', $string)[1]))[0];
echo $string;
Вы можете найти
s($fullString)->between("(", ")")полезным, как указано в эта автономная библиотека.