4

引用符で囲まれた部分文字列と引用符で囲まれていない部分文字列を含む文字列をPHPで分割したいと思います。
次の文字列があるとしましょう。

"this is a string" cat dog "cow"  

分割された配列は次のようになります。

array (  
[0] => "this is a string"  
[1] => "cat"  
[2] => "dog"  
[3] => "cow"  
)

私は正規表現に少し苦労していますが、1つの正規表現/preg_splitで達成することさえ可能かどうか疑問に思っています-Call...

私が最初に試したのは:

[[:blank:]]*(?=(?:[^"]*"[^"]*")*[^"]*$)[[:blank:]]*

ただし、これはarray[0]とarray[3]のみを正しく分割します。残りは文字ごとに分割されます。

次に、このリンクを見つけました:
区切り文字が引用符で囲まれていない限り、2つの区切り文字を含むPHPpreg_split

(?=(?:[^"]*"[^"]*")*[^"]*$)

これは私には良い出発点のように思えます。ただし、私の例の結果は、最初の正規表現の場合と同じです。

私は両方を組み合わせてみました-最初に引用符で囲まれた文字列用のもの、次に引用符で囲まれた文字列を省略すべき2番目のサブ正規表現(したがって[^ "]):

(?=(?:[^"]*"[^"]*")*[^"]*$)|[[:blank:]]*([^"].*[^"])[[:blank:]]*

したがって、2つの質問:

  1. たった1つのregex/preg_split-Callで私が望むことを達成することさえ可能ですか?
  2. はいの場合、正規表現を正しく組み立てる方法についてのヒントをいただければ幸いです。
4

1 に答える 1

4

一致は重複できないため、次のように使用できますpreg_match_all

preg_match_all('/"[^"]*"|\S+/', $input, $matches);

$matches[0]あなたが探しているものが含まれている必要があります。正規表現は、最初に引用符で囲まれた文字列との一致を試み、次に停止します。それが行われない場合は、できるだけ多くの非空白文字を収集します。交互に左から右に試行されるため、引用されたバージョンが優先されます。

編集:しかし、これは引用符を取り除くことはありません。これを行うには、キャプチャグループを使用できます。

preg_match_all('/(?|"([^"]*)"|(\S+))/', $input, $matches);

$matches[1]、あなたが探しているものが正確に含まれます。両方の(?|キャプチャグループが同じインデックスになるようにあります。

編集2:あなたは解決策を求めていたのでpreg_split、それも可能です。先読みを使用できます。これは、スペースの後に偶数の引用符が続くことを表明します(文字列の最後まで)。

$result = preg_split('/\s+(?=(?:[^"]*"[^"]*")*$)/', $input);

もちろん、これは引用符を取り除くことはありませんが、それは別のステップで簡単に行うことができます。

于 2012-11-08T15:29:33.580 に答える