ダブルクォーテーション含む文字列をスペースで分割するには


全文検索用にユーザー様がキーワードをGoogle検索のように、1つや、複数入力した場合、各キーワードを分割する方法を探しています。

半角及び全角スペースで区切られた下記の様な文字列を分割したいのですが、  
正規表現がわかりません。

### 分割条件

  1. 半角、全角、スペース区切り。
  2. 但し、ダブルクォーテーションで括られている文字列は中にスペースやタブなどの特殊文字が入っていても一つの文字列として扱う。  
従って、  
『ABC あいう"え "" おか きく"けこ -"おはよう"』を分割すると、  
『ABC』  
『あいう"え "" おか きく"けこ』 ← 途中に ""があるが、" "と間にスペースがないので連続した文字列と判断。  
『 -"おはよう"』  
の３つになります。

### 元の文字列の例

` きた A+!^"*-= " P" 雨 "" 雪 " "み ず た に" abc 時間123-"門`限" "やぶるな`

Java文字列リテラル表現では:

[code]

    String moto = "　きた　A+!^\"*-= \"　P\" 雨 \"\" 雪 \"　　　\"み　　ず た    に\"　　　　abc　時間123-\"門`限\"　 \"やぶるな";
    
[/code]

### 分割後の各文字列

  * `きた`
  * `A+!^"*-= "`
  * `P" 雨 "" 雪 "`
  * `"み ず た に"`
  * `abc`
  * `時間123-"門限"`
  * `"やぶるな` ←わざと最後のダブルクォーテーションを外してあります。

下記正規表現でできる？かもしれませんが、このコードをJAVAへ記述すると、  
実行以前の問題で、eclipsで記述文字列が正しくないエラーで赤く指摘状態になります。  
（恐らく`\`を追加したりしてエスケープ処理をしないといけないのですが、`\`を`/`や`"`の前にいくつ追加しても、文字列が正しくないというエラーで赤く指摘状態になります。）

[code]

    Pattern p = Pattern.compile("\s+("(?:"|[^"])*"?|[^"]\S*)");
    String[] result = p.split(moto);
    for (int i=0; i<result.length; i++){
        System.out.println("[" + result[i] + "]");
    }
    
[/code]

### 質問 １

正規表現は、正しいでしょうか？

### 質問 ２

Javaに記述するには、\を追加などして、どのように記述すれば、Eclipseが文字列が不正というエラーをださなくなるでしょうか？

やった見ている多数のパターンの一例ですが、

[code]

    Pattern p = Pattern.compile("\\s+(\"(?:\"|[^\"])*\"?|[^\"]\S*)");
    
[/code]

* * *

下記の様に \ を入れたところ、eclipsで赤文字で、文字列エラーがなくなりました。

[code]

    String[] result = test.split("\\s+(\"(?:\"|[^\"])*\"?|[^\"]\\S*)");
    for (int i=0; i<result.length; i++){
        out.print("[" + result[i] + "]");
    }
    
[/code]

但し、正規表現が悪いようで、下記の様に分割できませんでした。  
`test = "雨 "み ず"";`  
↓ 分割後  
`[雨 "み ず"]`




ほぼ解決策が見えてきているときに別解もなんなんですが、その仕様( _正解は、`[A+!^"*-=
P"]`_)ならば、正規表現でも実現できますよということで。

[code]

        String moto = " きた A+!^\"*-= P\" 雨 \"\" 雪 \" \"み ず た に\" abc 時間123-\"門`限\" \"やぶるな";
        Pattern p = Pattern.compile("((?:[^\\s　\"\\\\]|\\\\.|\"(?:\\\\.|[^\\\\\"])*(?:\"|$))+)");
        Matcher m = p.matcher(moto);
        while( m.find() ) {
            System.out.println("["+m.group(1)+"]");
        }
    
[/code]

出力:

[code]

    [きた]
    [A+!^"*-= P"]
    [雨]
    [""]
    [雪]
    [" "み]
    [ず]
    [た]
    [に" abc 時間123-"門`限" "やぶるな]
    
[/code]

質問文にある期待結果と随分違う結果に見えますが、最初の`A+!^"*-=`が`A+!^"*-=
P"`になって、`"`で挟まれる範囲が交互になることを考えると、 _★分割条件_ に従えばこの結果になるはずです。

アイデアとしては

  * 「空白と`"`, `\`」以外の文字
  * `\`+一文字
  * `"`から「`"`または文字列末」まで

をひとかたまりと考えて、最長一致(正規表現のデフォルト)でそのかたまりの連続を抜き出す、というものです。

お時間が取れるようでしたら、是非お試しください。

(少し前に書いたコードですが、「動作が違う」と言われたらどこを直すのか、かなり悩んでしまいそうです。やはりこの辺の処理はわかりやすさ優先にした方が良いかもしれません。)

