web-dev-qa-db-ja.com

PHP:括弧内のテキストを抽出する最良の方法は?

括弧の間のテキストセットを抽出するための最良/最も効率的な方法は何ですか?可能な限り最も効率的な方法で、「これ(テキスト)以外のすべてを無視する」という文字列から「テキスト」という文字列を取得したいとします。

これまでのところ、私が思いついた最高のものはこれです:

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

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

これを行うためのより良い方法はありますか?一般的に正規表現を使用すると効率が低下する傾向があることはわかっていますが、関数呼び出しの回数を減らすことができない限り、おそらくこれが最善の方法でしょうか?考え?

68
Wilco

私はただ正規表現をして、それをやり直したいと思います。巨大なパフォーマンスの問題になるほど十分な反復を行っていない限り、コーディングが簡単です(そして、振り返ってみるとわかります)

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

正規表現を使用します。

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

これは、「[」と「]」の間のすべてのテキストを抽出し、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( "hello [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"
}
3
Sachin Murali G

この機能は役に立つかもしれません。

    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
vijay
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
user628176

既に投稿されている正規表現ソリューション-\((.*?)\)および\(([^\)]+)\)-開き括弧と閉じ括弧の間にinnermost文字列を返しません。文字列が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_一致リセット演算子を使用して)除外します。 _(?<=\()_は、現在の場所のすぐ左に表示される_(_を必要とする肯定的な後読みですが、後読み(ルックアラウンド)パターンはないため、一致値に_(_は追加されません消費する。 _(?=\()_は、現在の場所のすぐ右に_)_ charが必要な正の先読みです。

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