【问题标题】:PHP: Best way to extract text within parenthesis?PHP:提取括号内文本的最佳方法?
【发布时间】:2010-09-16 19:51:00
【问题描述】:

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

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

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

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

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

【问题讨论】:

标签: php parsing string


【解决方案1】:

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

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

【讨论】:

  • 不,不是:。只匹配单个字符。
  • 不一定,?是懒惰的比赛。没有它,一个像'ignore (everything) except this (text)' 这样的字符串,匹配最终会是'everthing) except this (text'
  • 很高兴知道。应该避免所有那些平方不。例如。 /src="([^"]*)"/ 现在替换为 /src="(.*?)"/ :D
  • /src="([^"]*)"/ 比 /src="(.*?)"/ 效率更高
  • 如果我想要除了(文本)那么?
【解决方案2】:

所以,实际上,您发布的代码不起作用:substr()'s 参数是 $string、$start 和 $lengthstrpos()'s 参数是 $haystack$needle .稍作修改:

$str = "忽略除此(文本)之外的所有内容";
$start = strpos($str, '(');
$end = strpos($str, ')', $start + 1);
$length = $end - $start;
$result = substr($str, $start + 1, $length - 1);

一些微妙之处:我在 offset 参数中使用了$start + 1,以便在对第二个括号进行@​​987654326@ 搜索时帮助PHP;我们将$start 加一并减少$length 以从匹配中排除括号。

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

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

【讨论】:

  • 请注意,如果您修改此代码以在 $end 上使用 strrpos (从字符串的后面开始),那么它将正确处理其中有括号的情况......就像(这是(非常)好)。
【解决方案3】:

使用正则表达式:

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

【讨论】:

    【解决方案4】:

    我认为这是获取字符串中第一个括号之间的单词的最快方法。

    $string = 'ignore everything except this (text)';
    $string = explode(')', (explode('(', $string)[1]))[0];
    echo $string;
    

    【讨论】:

      【解决方案5】:

      这是一个示例代码,用于提取 '[' 和 ']' 之间的所有文本并将其存储到 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。
      【解决方案6】:

      这个功能可能有用。

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

      【讨论】:

        【解决方案7】:

        已发布的正则表达式解决方案 - \((.*?)\)\(([^\)]+)\) - 不返回左括号和右括号之间的 innermost 字符串。如果一个字符串是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 匹配重置运算符)。 (?&lt;=\() 是正向后视,它要求 ( 立即出现在当前位置的左侧,但 ( 不会添加到匹配值中,因为后视(环视)模式不消耗。 (?=\() 是一个正向前瞻,它要求 ) 字符立即出现在当前位置的右侧。

        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   )
        

        【讨论】:

          【解决方案8】:
          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]') 将返回:

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-04
            相关资源
            最近更新 更多