PHP:在括号内提取文本的最佳方法?

问题描述 投票:65回答:7

在括号之间提取文本集的最佳/最有效方法是什么?假设我想以最有效的方式从字符串“忽略除此(文本)之外的所有内容”中获取字符串“text”。

到目前为止,我提出的最好的是:

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

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

有一个更好的方法吗?我知道通常使用正则表达式往往效率较低,但除非我可以减少函数调用的数量,否则这可能是最好的方法吗?思考?

php parsing string
7个回答
116
投票

我只是做一个正则表达式并完成它。除非你做了足够的迭代以致它成为一个巨大的性能问题,它只是更容易编码(并且当你回顾它时理解)

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

12
投票

所以,实际上,你发布的代码不起作用:substr()'s参数是$ string,$ start和$ length,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,以便在第二个括号中进行strpos()搜索时帮助PHP输出;我们增加$start并减少$length以从匹配中排除括号。

此外,在此代码中没有错误检查:在执行$start之前,您需要确保$endsubstr不=== false。

至于使用strpos/substr与正则表达式;在性能方面,这段代码将击败正则表达式。虽然这有点讽刺。我吃和呼吸strpos/substr,所以我不太介意,但其他人可能更喜欢正则表达式的紧凑性。


8
投票

使用正则表达式:

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
投票

此功能可能很有用。

    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()=>用于查找字符串中第一次出现的位置。

strpos()=>用于查找字符串中第一次出现的位置。


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

这是对前一个答案的一点改进,它将以数组形式返回所有模式:

get String Between('[This [] is [test] string [pattern]')将返回:


0
投票

已发布的正则表达式解决方案 - \((.*?)\)\(([^\)]+)\) - 不会返回开括号和近括号之间的最里面的字符串。如果一个字符串是Text (abc(xyz 123)他们both return一个(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个字符,请用(替换)

细节:

  • \( - 一个开放的圆括号(必须转义以表示字面括号,因为它在字符类之外使用)
  • [^()]* - 除了zero or more(之外的)字符(注意这些()不必在其内部的字符类中进行转义,()不能用于指定分组并被视为字面括号)
  • \) - 一个结束圆括号(必须转义以表示字面括号,因为它在字符类之外使用)。

替代正则表达式中的\(\K部分匹配(并从匹配值中省略(使用\K匹配重置运算符)。 (?<=\()是一个积极的lookbehind,需要(立即出现在当前位置的左侧,但(没有添加到匹配值,因为lookbehind(环视)模式不消耗。 (?=\()是一个积极的前瞻,需要一个)字符立即出现在当前位置的右侧。

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
}

输出:

Array ( [0] => (text)  [1] => (text here) )
Array ( [0] => text    [1] => text here   )
© www.soinside.com 2019 - 2024. All rights reserved.