1

わかりました、これを英語で説明するのは本当に難しいので、例を挙げましょう。

次の形式の文字列を使用します。

key-value;key1-value;key2-...

データを抽出して配列にする必要があります

array('key'=>'value','key1'=>'value1', ... )

私はこの機能(のほとんど)を実現するためにregexpを使用することを計画しており、次の正規表現を記述しました。

/^(\w+)-([^-;]+)(?:;(\w+)-([^-;]+))*;?$/

使用するpreg_matchコードとこのコード:

for ($l = count($matches),$i = 1;$i<$l;$i+=2) {
    $parameters[$matches[$i]] = $matches[$i+1];
}

ただし、正規表現は明らかに4つの後方参照(入力文字列の最初と最後のキーと値のペア)のみを返します。これを回避する方法はありますか?正規表現を使用して文字列の正確さをテストし、PHPをループで使用して完璧な結果を得ることができることは知っていますがexplode、正規表現でそれが可能かどうかは本当に興味があります。

key-value;つまり、正規表現を使用して、これらのペアの任意の数を文字列に取り込む必要があります。

4

6 に答える 6

2

正規表現は強力なツールですが、最善のアプローチではない場合もあります。

$string = "key-value;key1-value";
$s = explode(";",$string);
foreach($s as $k){
    $e = explode("-",$k);
    $array[$e[0]]=$e[1];
}
print_r($array);
于 2010-02-11T15:15:32.470 に答える
2

preg_match_all()代わりに使用してください。多分次のようなものです:

$matches = $parameters = array();
$input = 'key-value;key1-value1;key2-value2;key123-value123;';

preg_match_all("/(\w+)-([^-;]+)/", $input, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
   $parameters[$match[1]] = $match[2];
}

print_r($parameters);

編集:

入力文字列がパターンに準拠しているかどうかを最初に検証してから、次を使用します。

if (preg_match("/^((\w+)-([^-;]+);)+$/", $input) > 0) {
    /* do the preg_match_all stuff */
}       

EDIT2:最後のセミコロンはオプションです

if (preg_match("/^(\w+-[^-;]+;)*\w+-[^-;]+$/", $input) > 0) {
    /* do the preg_match_all stuff */
}       
于 2010-02-11T15:19:06.253 に答える
2

先読みを使用して、一致を抽出するときに入力を検証できます。

/\G(?=(?:\w++-[^;-]++;?)++$)(\w++)-([^;-]++);?/

(?=(?:\w++-[^;-]++;?)++$)検証部分です。入力が無効な場合、マッチングはすぐに失敗しますが、正規表現が適用されるたびに先読みが評価されます。それを(残りの正規表現とともに)キーと値のペアと同期させるために、私は\G各一致を前の一致が終了した場所に固定するために使用しました。

このように、先読みが最初に成功した場合、それ以降は毎回成功することが保証されます。明らかに、それは可能な限り効率的ではありませんが、それはおそらく問題にはならないでしょう-あなたのテストだけが確実に知ることができます。

先読みが失敗した場合、preg_match_all()はゼロ(false)を返します。成功すると、一致は配列の配列で返されます。1つは完全なキーと値のペア、もう1つはキー、もう1つは値です。

于 2010-02-11T22:09:34.827 に答える
0

いいえ。新しい一致は古い一致を上書きします。おそらく、のlimit議論はexplode()爆発するときに役立つでしょう。

于 2010-02-11T15:15:08.257 に答える
0

^検証とデータにアンカー(と$)が必要なため、1つの正規表現でデータの検証と抽出の両方を実行できるとは思いませんが、preg_match_all()アンカーを使用するpreg_match_all()と、最後に一致したセットのみが返されます。

于 2010-02-11T17:41:22.503 に答える
0

このソリューションはどうですか?

$samples = array(
    "good" => "key-value;key1-value;key2-value;key5-value;key-value;",
    "bad1" => "key-value-value;key1-value;key2-value;key5-value;key-value;",
    "bad2" => "key;key1-value;key2-value;key5-value;key-value;",
    "bad3" => "k%ey;key1-value;key2-value;key5-value;key-value;"
);

foreach($samples as $name => $value) {
    if (preg_match("/^(\w+-\w+;)+$/", $value)) {
        printf("'%s' matches\n", $name);
    } else {
        printf("'%s' not matches\n", $name);
    }
}
于 2010-02-11T16:52:45.643 に答える