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


83

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

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

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

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

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


回答:


144

正規表現を実行して、それを乗り越えます。パフォーマンスの大きな問題になるほど十分な反復を行っていない限り、コーディングは簡単です(そして振り返ってみると理解できます)。

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

1
いいえ、そうではありません:。1文字のみに一致します。
エドワードZ.ヤン

1
必ずしも、 ?怠惰な試合です。それがないと、「これ(テキスト)を除いて(すべて)を無視する」のような文字列、これを除いて「すべて」になります(テキスト」
Owen

1
知っておくと良い。それらすべての四角いnotを避けるべきです。例:/ src = "([^"] *) "/は/src="(.*?)"/に置き換えられました:D
Dimitry

「振り返ってみるとわかる」といいですね。それができない場合は、それを明確にするためにいくつかのStackOverflowコメントがあります。
Mnebuerquo 2008年

2
/ src = "([^"] *) "/は/src="(.*?)"/よりも効率的です
Tanj

14

したがって、実際には、投稿したコードは機能しません。substr()'sパラメーターは$ string、$ start、および$ lengthであり、strpos()'sパラメーターは$haystack$needleです。わずかに変更:

$ str = "これ(テキスト)以外はすべて無視する";
$ start = strpos($ str、 '(');
$ end = strpos($ str、 ')'、$ start + 1);
$ length = $ end- $ start;
$ result = substr($ str、$ start + 1、$ length-1);

いくつかの微妙な点:2番目の括弧で検索$start + 1を実行しているときにPHPを支援するために、offsetパラメーターで使用しましたstrpos()$start1をインクリメントし、縮小$lengthして括弧を一致から除外します。

また、このコードにはエラーチェックは$startあり$endませんsubstr。を実行する前に、=== falseではないことを確認する必要があります。

使用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でのみ使用される可能性があるためです。
マイクカストロデマリア2014

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)、彼らは両方 返す(abc(xyz 123)マッチ全体として、そしてません(xyz 123)

一致に括弧を含める必要がある場合、括弧内の部分文字列に一致するパターン(withpreg_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一致リセット演算子を使用)。(?<=\()はポジティブルックビハインドであり(、現在の場所のすぐ左にを表示する必要があり(ますが、ルックビハインド(ルックアラウンド)パターンは消費されないため、は一致値に追加されません。(?=\()は前向きな先読みであり)、現在の場所のすぐ右側に文字を表示する必要があります。

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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.