web-dev-qa-db-ja.com

2つの文字列の間のコンテンツを取得PHP

Whatsは、2つの文字列の間のコンテンツを取得するための最良の方法です。

ob_start();
include('externalfile.html'); ## see below
$out = ob_get_contents();
ob_end_clean();

preg_match('/{FINDME}(.|\n*)+{\/FINDME}/',$out,$matches);
$match = $matches[0];

echo $match;

## I have used .|\n* as it needs to check for new lines. Is this correct?

## externalfile.html

{FINDME}
Text Here
{/FINDME}

何らかの理由で、これは私のコードのある場所で機能し、別の場所では機能しないようです。私はこれを正しい方法で行っていますか?それとももっと良い方法がありますか?

また、出力バッファはこれを行う方法ですか、それともfile_get_contentsですか?

前もって感謝します!

24
Lizard
  • 使用する # の代わりに /したがって、それらをエスケープする必要はありません。
  • modifiers.および\sには改行も含まれます。
  • {および}には、nからm回までのさまざまな機能があります{n,m}
  • 基本

    preg_match('#\\{FINDME\\}(.+)\\{/FINDME\\}#s',$out,$matches);
    
  • さまざまなタグなどの高度な設定(JavaScriptではスタイリングはそれほど良くありません)。

    $delimiter = '#';
    $startTag = '{FINDME}';
    $endTag = '{/FINDME}';
    $regex = $delimiter . preg_quote($startTag, $delimiter) 
                        . '(.*?)' 
                        . preg_quote($endTag, $delimiter) 
                        . $delimiter 
                        . 's';
    preg_match($regex,$out,$matches);
    

このコードを関数に入れます

  • strayphpコードを実行したくないファイルについては、file_get_contentsを使用する必要があります。 include/requireはそこにオプションであってはなりません。
42
OIS

これにはsubstrとstrposを使用することもできます。

$startsAt = strpos($out, "{FINDME}") + strlen("{FINDME}");
$endsAt = strpos($out, "{/FINDME}", $startsAt);
$result = substr($out, $startsAt, $endsAt - $startsAt);

FINDMEが実行されない場合に対処するには、エラーチェックを追加する必要があります。

43
Adam Wright

私はこれら2つのソリューションが大好きです

function GetBetween($content,$start,$end)
{
    $r = explode($start, $content);
    if (isset($r[1])){
        $r = explode($end, $r[1]);
        return $r[0];
    }
    return '';
}


function get_string_between($string, $start, $end){
    $string = " ".$string;
    $ini = strpos($string,$start);
    if ($ini == 0) return "";
    $ini += strlen($start);   
    $len = strpos($string,$end,$ini) - $ini;
    return substr($string,$ini,$len);
}

また、上記の両方のソリューションを使用してベンチマークをいくつか作成しましたが、どちらもほぼ同じ時間です。あなたもそれをテストすることができます。私は両方の関数に約60000文字(Ms. WordのWordカウントで確認)のファイルを読み取らせ、両方の関数の検索に約0.000999秒かかりました。

$startTime = microtime(true);
GetBetween($str, '<start>', '<end>');
echo "Explodin Function took: ".(microtime(true) - $startTime) . " to finish<br />";

$startTime = microtime(true);
get_string_between($str, '<start>', '<end>');
echo "Subsring Function took: ".(microtime(true) - $startTime) . " to finish<br />";
4

可能であれば正規表現の使用を避けたいので、2つの文字列の間のすべての文字列をフェッチして配列を返す別のソリューションを次に示します。

function getBetween($content, $start, $end) {
    $n = explode($start, $content);
    $result = Array();
    foreach ($n as $val) {
        $pos = strpos($val, $end);
        if ($pos !== false) {
            $result[] = substr($val, 0, $pos);
        }
    }
    return $result;
}
print_r(getBetween("The quick brown {{fox}} jumps over the lazy {{dog}}", "{{", "}}"));

結果 :

Array
(
    [0] => fox
    [1] => dog
)
2
Donovan P

改行はRegExで問題を引き起こす可能性があります。処理する前に、それらを削除するか\ nに置き換えてみてください。

1
Cem Kalyoncu

これは、PHPソリューションで、干し草のタグの間にある文字列を返すソリューションです。動作しますが、効率をテストしていません。これが必要で、このページのAdam Wrightの回答に触発されました。

$ haystackの$ tagと$ end_symbold。$ tagの間にあるすべての文字列を含むarray()を返します。$ hay_stackに$ end_symbol。$ tagが見つからないためにタグペアが存在しない場合はFALSEを返します。

function str_between_tags($haystack, $tag, $end_symbol){
    $c_end_tags = substr_count($haystack, $end_symbol.$tag);
    if(!$c_end_tags) return FALSE;

    for($i=0; $i<$c_end_tags; $i++){
        $p_s = strpos($haystack, $tag, (($p_e)?$p_e+strlen($end_symbol.$tag):NULL) ) + strlen($tag );
        $p_e = strpos($haystack, $end_symbol.$tag, $p_s);
        $result[] = substr($haystack, $p_s, $p_e - $p_s);
    }
    return $result;
}
0
function getInbetweenStrings($start, $end, $str){
    $matches = array();
    $regex = "/$start([a-zA-Z0-9_]*)$end/";
    preg_match_all($regex, $str, $matches);
    return $matches[1];
}


$str = "C://@@ad_custom_attr1@@/@@upn@@/@@samaccountname@@";
$str_arr = getInbetweenStrings('@@', '@@', $str);

print_r($str_arr);
0
Ravi Verma