0

テンプレートクラスに取り組んでいますが、文字列引数リストから引用符で囲まれた文字列のリストを解析しようとすると問題が発生します。たとえば、文字列を見てください。

$string = 'VAR_SELECTED, \'Hello m\'lady\', "null"';

文字列「Hellom'lady」と「null」を抽出する正規表現を思い付くのに問題があります。私が持っている最も近いものは

$string = 'VAR_SELECTED, \'Hello m\'lady\', "null", \'TE\'ST\'';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);

どの出力:

Array
(
    [0] => Array
        (
            [0] => VAR_SELECTED, 
            [1] => 'Hello m'lady', 
            [2] => "null", 
            [3] => 'TE'ST'
        )

)

ただし、次のより複雑なケース:

$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);  

出力:

Array
(
    [0] => Array
        (
            [0] => VAR_SELECTED, 
            [1] => 'Hello 
            [2] => "Father"
            [3] => ', 
            [4] => "Hello 
            [5] => 'Luke'
            [6] => "
        )

)

誰かが私がこの問題を解決するのを手伝ってもらえますか?複数の正規表現は今後の方向性ですか?

編集文字列内のコンマをプレースホルダーに置き換えてから、文字列を分解して分解する方が簡単かもしれません。

編集2単純な安全でないオプション(私は使用しません)を考えましたが、E_NOTICEエラーが生成されます。

$string = 'return array(VAR_SELECTED, \'Hello , "Father"\', "Hello \'Luke\'4");';
$string = eval($string);
print_r($string);
4

3 に答える 3

3

これを試して:

/(?<=^|[\s,])(?:(['"]).*?\1|[^\s,'"]+)(?=[\s,]|$)/

または、PHPの一重引用符で囲まれた文字列リテラルとして:

'/(?<=^|[\s,])(?:([\'"]).*?\1|[^\s,\'"]+)(?=[\s,]|$)/'

その正規表現は望ましい結果をもたらしますが、あなたはこれについて間違っていると思います。通常、引用符で囲まれた文字列にリテラルの引用符文字を含める必要がある場合は、円記号または別の引用符を使用して引用符をエスケープします。あなたはそれをしていないので、私は見回しに基づいて壊れやすいハックを使わなければなりませんでした。データがこのように見えるはずではないのですか?

$string = 'VAR_SELECTED, \'Hello m\\'lady\', "null"';

$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \\'Luke\\'"';

そういえば、PHPにはCSVデータのサポートが組み込まれていませんか?

于 2010-07-10T18:49:25.153 に答える
1

これが私がそれをする方法です:

タスクを、実行するコンポーネントのステップに分割します。

1.)文字列をコンマで分解します。

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello m\'lady\'"
[2]=>" "null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello "Father"\'"
[2]=>" "Hello \'Luke\'""

2.)3つすべてでTrimを実行して、空白を取り除きます

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello m\'lady\'"
[2]=>""null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello "Father"\'"
[2]=>""Hello \'Luke\'""

3.)str_replace( "\"、 ""、$ text)を実行して、スラッシュを削除します。(スペースを削除します。読みやすさのためにのみ追加されているため、裸のスラッシュと「空の」文字列にする必要があります)

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello m'lady'"
[2]=>""null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello "Father"'"
[2]=>""Hello 'Luke'""

4.)トリムを再度実行します。trim($ text、 "'" ")のみ(スペースを削除します。読みやすくするために追加)

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello m'lady"
[2]=>"null"

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello "Father""
[2]=>"Hello 'Luke'"

私はこれをテストしていませんが、論理は健全です。(私の経験では)すべての正規表現の98%をテストするための迅速で汚い方法は、http://rubular.com/を使用する ことです。これは素晴らしいサイトです。通常、正規表現で窒息し始めた場合、問題をさらに分解する必要があるというのが私の最初の兆候です。(それはただの意見です〜防炎スーツを着用します〜)

于 2010-07-10T17:30:41.203 に答える
0

一致文字列で後方参照を使用したい。

preg_match_all('@([\'"]).*[^\\\\]\1@', $string, $matches);

これにより、「または」の最初のインスタンスとの照合が開始され、その後、エスケープされていない「または」の一致で終わる最長の文字列と照合されます。

Array (
[0] => Array
    (
        [0] => 'Hello m'lady', "null", 'TE'ST'
    )

[1] => Array
    (
        [0] => '
    )
于 2010-07-10T17:15:58.223 に答える