3

バックグラウンド

0d0ausingの出現ごとに文字列を分割して作成した配列がありますpreg_split('/(?<=0d0a)(?!$)/')

例えば:

$string = "78781110d0a78782220d0a";

次のように分割されます。

Array ( [0] => 78781110d0a [1] => 78782220d0a )  

有効な配列要素は、で始まり、7878で終わる必要があり0d0aます。

問題

しかし、場合によって0d0aは、文字列に追加の無効な配列要素に分割されるものがあります。つまり、それは で始まりません7878

たとえば、次の文字列を使用します。

$string = "78781110d0a2220d0a78783330d0a";

これは次のように分割されます。

Array ( [0] => 78781110d0a [1] => 2220d0a [2] => 78783330d0a )

しかし、実際には次のようにする必要があります。

Array ( [0] => 78781110d0a2220d0a [1] => 78783330d0a)

私の解決策

これを回避するために、次の(面倒な)コードを作成しました。

    $data = Array('78781110d0a','2220d0a','78783330d0a');
    $i = 0; //count for $data array;
    $j = 0; //count for $dataFixed array;
    $dataFixed = $data;

    foreach($data as $packet) {
        if (substr($packet,0,4) != "7878") { //if packet doesn't start with 7878, do some fixing
            if ($i != 0) { //its the first packet, can't help it!
                $j++;                    

                if ((substr(strtolower($packet), -4, 4) == "0d0a")) { //if the packet doesn't end with 0d0a, its 'mostly' not valid, so discard it
                    $dataFixed[$i-$j] = $dataFixed[$i-$j] . $packet;
                }
                    unset($dataFixed[$i-$j+1]);                        
                    $dataFixed = array_values($dataFixed);
            }
        }
        $i++;
    }

説明

最初に配列を別の配列にコピーします$dataFixed。配列のforeachループで、$dataで始まるかどうかを確認し7878ます。そうでない場合は、前の配列と結合し$dataます。次に、現在の配列の設定を解除し$dataFixed、配列要素を でリセットしarray_valuesます。

しかし、私はこの解決策についてあまり自信がありません..より良い、より効率的な方法はありますか?

アップデート

0d0a入力文字列が想定どおりに終わらない場合はどうなりますか? 前の配列要素に固執します..

例: string78781110d0a2220d0a78783330d0a0000では、0000別の配列要素として分離する必要があります。

4

3 に答える 3

1

たまたまコンテンツの一部でもある区切り文字「0d0a」を使用していると思います。区切り文字もコンテンツの一部である限り、ジャンク データの取得を避けることはできません。どういうわけか、区切り文字は一意でなければなりません。

可能な解決策。

  • 区切り記号をデータの一部として発生しない別のものに変更します (000000, @!.;)
  • 簡単アレンジアイテムのテキストの長さがはっきりしている場合は、それを使用してください。例によると、それは不可能です。

あなたが共有したサンプルデータのみを考慮した回答で与えられたソリューション。文字列の内容に自信がある場合は、他の人が提供したこれらのソリューションを使用するのが非常に適しています。そうでなければ、これらのソリューションは保証を保証しません!

最善の解決策:正しい区切り文字を修正してから、正規表現を使用するか、好きなものを爆発させます。

于 2013-04-12T05:50:06.937 に答える
1

代わりにpreg_match_allを使用しないのはなぜですか? 非キャプチャ グループ (先読み、後読み) をすべて回避して、文字列を分割し (非キャプチャ グループがないと一致が削除されます)、探している一致を見つけることができます。

更新しました

<?php
$string = "00787817878110d0a22278780d0a78783330d0a00";
preg_match_all('/7878.*?0d0a(?=7878|[^(7878)]*?$)/', $string, $arr);
print_r($arr);
?>

配列を与え$arr[0] => ( [0] => 787817878110d0a22278780d0a, [1] => 78783330d0a )ます。先頭と末尾のガベージ文字を取り除きます (または で開始または終了しないものは何7878でも.78780d0a

$arr[0] は、探している値の配列になります。

ideone の例を参照してください

複数の7878値と複数の0d0a値で動作します (ばかげていますが)。

アップデート

分割の方が好みなら、正規表現を完全に避けてみませんか?

<?php
$string = "787817878110d0a22278780d0a78783330d0a";
$arr = explode('0d0a7878', $string);
$string = implode('0d0a,7878', $arr);
$arr = explode(',', $string);
print_r($arr);
?>

ここでは、文字列を delimiter0d0a7878で分割します。これは、@CharlieGorichanaz のソリューションが行っていることであり、迅速で正確なソリューションのために彼に支持されます。次にカンマを追加します。なぜなら、カンマで区切られた値が嫌いな人はいないからです。そして、必要な値の配列のコンマで再び分解します。パフォーマンスに関しては、これは正規表現を使用するよりも高速になるはずです。を参照してください。

于 2013-04-12T05:46:54.430 に答える