2009-11-12 2 views
7

文字列をスペースで区切る必要がありますが、引用符のフレーズは分割しないで保存する必要があります。例:引用符間の空白を除くすべての空白を見つける方法はありますか?

word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5 

これは、preg_split後、アレイを生じるはずである:

array(
[0] => 'word1', 
[1] => 'word2', 
[2] => 'this is a phrase', 
[3] => 'word3', 
[4] => 'word4', 
[5] => 'this is a second phrase', 
[6] => 'word5' 
) 

どのように私はそれを行うには、私の正規表現を構成する必要がありますか?

PS。 related questionがありますが、私のケースではうまくいかないと思います。受け入れられた答えは空白の代わりに単語を見つける正規表現を提供します。

+0

関連する質問は、両方の例をもとに、あなたがしたいことを正確に示しています。あなたは受け入れられた答えを試しましたか?何が起こった? – richsage

+0

うん、私はそれを試した。私はPHPではなく、.NETを使用します。私は正規表現の結果をインラインでフィルタリングすることはできません。そして、私が言ったように、\ w + | "[\ w \ s] *"は私のためにはうまくいきません – altern

答えて

8

#regex IRCチャンネルからユーザーMizardXの助けを借りて(irc.freenode.net:それにもかかわらず、ここに別の方法があります)溶液が見出された。一重引用符もサポートしています。

$str= 'word1 word2 \'this is a phrase\' word3 word4 "this is a second phrase" word5 word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; 

$regexp = '/\G(?:"[^"]*"|\'[^\']*\'|[^"\'\s]+)*\K\s+/'; 

$arr = preg_split($regexp, $str); 

print_r($arr); 

結果は次のとおりです。

Array (
    [0] => word1 
    [1] => word2 
    [2] => 'this is a phrase' 
    [3] => word3 
    [4] => word4 
    [5] => "this is a second phrase" 
    [6] => word5 
    [7] => word1 
    [8] => word2 
    [9] => "this is a phrase" 
    [10] => word3 
    [11] => word4 
    [12] => "this is a second phrase" 
    [13] => word5 
) 

PS。この正規表現はPCRE 7でしか動作しません。

プロダクションサーバではPCRE 7のサポートはなく、そこにPCRE 6だけがインストールされていることが判明しました。それは(\ G及び\ Kを処分した)PCRE 7の前の一つで動作する正規表現ほど柔軟ではないにもかかわらず:与えられた入力結果の

/(?:"[^"]*"|\'[^\']*\'|[^"\'\s]+)+/ 

上記と同様です。

+0

\ Gと\ Kは何を表しますか? – Amarghosh

+1

'\ G'は前回の試合が終了した場所(大まかに言えば)に前回の試合がなかった場合は入力の先頭にマッチします。 '\ K'私は見上げなければなりませんでした。正規表現はそれに続くトークンと空白にマッチしますが、空白にマッチしたように動作します。一種の貧しい人の視線を引きずって、ほとんどの場合、視覚障害者よりも優れているように思えるだけです。なぜその機能がより一般的ではないのだろうか? http://www.pcre.org/pcre.txt –

+0

ありがとうアラン。 regex.infoの両方で見つけることができませんでした...正規表現のためにGoogleにとって非常に難しいです。 – Amarghosh

0

あなたの引用符がよく定義されていると仮定すると、すなわちペアでは、2つのフィールドごとに爆発してループすることができます。例えば

$str = "word1 word2 \"this is a phrase\" word3 word4 \"this is a second phrase\" word5 word6 \"lastword\""; 
print $str ."\n"; 
$s = explode('"',$str); 
for($i=1;$i<count($s);$i+=2){ 
    if (strpos($s[$i] ," ")!==FALSE) { 
     print "Spaces found: $s[$i]\n"; 
    } 
} 

出力

$ php test.php 
Spaces found: this is a phrase 
Spaces found: this is a second phrase 

複雑な正規表現は必要ありません。

+0

確かに私は正規表現なしでこれを行うことができました。 – altern

0

これをリンクした他の質問の正規表現を使用するのは簡単ですか?

<?php 

$string = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; 

preg_match_all('/(\w+|"[\w\s]*")+/' , $string , $matches); 

print_r($matches[1]); 

?> 

出力:

Array 
(
    [0] => word1 
    [1] => word2 
    [2] => "this is a phrase" 
    [3] => word3 
    [4] => word4 
    [5] => "this is a second phrase" 
    [6] => word5 
) 
+0

また、特定の文字(アンパサンドなど)もありますか?アンパサンドだけでなく未処理のものもあります。さらに、異なるシンボルは異なって扱われるべきです。たとえば、中括弧が見つかった場合は、それらを検索結果に含める必要があります。 – altern

+1

@altern、まあ、 'edds'はあなたのニーズに彼の例を調整しても大丈夫だと確信しています... –

0

誰もが正規表現対ベンチマークトークン化にしたいですか?私の推測では、explode()関数は少しの速度の利点のためにあまりにも重いです。

(私は引用符で囲まれた文字列を格納するための他のケースを忘れてしまったので、編集した)

$str = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; 

// initialize storage array 
$arr = array(); 
// initialize count 
$count = 0; 
// split on quote 
$tok = strtok($str, '"'); 
while ($tok !== false) { 
    // even operations not in quotes 
    $arr = ($count % 2 == 0) ? 
           array_merge($arr, explode(' ', trim($tok))) : 
           array_merge($arr, array(trim($tok))); 
    $tok = strtok('"'); 
    ++$count; 
} 

// output results 
var_dump($arr); 
0
$test = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; 
preg_match_all('/([^"\s]+)|("([^"]+)")/', $test, $matches); 
関連する問題