2016-07-05 2 views
0

私はJavaでプログラムを作成しており、正規表現を使用してわずかな問題に遭遇しました。私は引用符で囲まれていないものすべてを取得したい。私は正規表現のパターンがright hereですが、問題はJavaで使用できないということです。それは(*SKIP)(*F)トリックを使用して".*"をスキップし、他のものを見つける([^\W]を使用)が、私が言ったように、それはJavaでは使用できません。私は近いパターンですが、必要なものではありません。right here。それは、それの前または後ろに直接引用符を持たないすべてを見つけるでしょう。その問題は、もし私がこのようなものを持っているならば:Test1 "Hello World!" Test2、そしてTest1Test2、そしてWorldをつかむでしょう。引用符で囲まれているので、私はWorldを得たくありません。私が知りたいことは、私が望むことをすることさえ可能であるかどうか、そしてもしそうなら、そうです。単純なJava Regex(* SKIP)(* F)の代替はありますか?

+0

引用符について確信があるならば、この正規表現 '[^"] ++((?= "(?<= \ b))| \ s * $)'がそれを行います。 [デモ](https://regex101.com/r/rX4aY1/1) – revo

+0

@revo事は、それはスペースをつかむことです。 '[^ \ W]'(私はそれを理解することはできません:P) – mttprvst13

+0

私は答えを追加しますように、スペースを取得する方法はありますか? – revo

答えて

0

これらの動詞は、正規表現エンジン(この場合はPCRE)にそれらの一致を破棄するよう伝えるのに非常に便利な方法です。

Javaはこれらの動詞を持っていませんが、あなたは動詞(*SKIP)(*F)せずにJavaを同じアプローチを使用することができ、あなたが使用できるように、その後...あなたが望むコンテンツをキャプチャ:

".*"|([^\W]+) 
or 
".*"|(\w+) 

そしてつかみます捕捉グループからのコンテンツは、1

String text = "test1 \"hello world!\" test2"; 

Pattern ptrn = Pattern.compile("\".*\"|([^\\W]+)"); 
Matcher m = ptrn.matcher(text); 

while (m.find()) { 
    if (m.group(1) != null) { 
     System.out.println("Text: "+m.group(1)); 
    } 
} 

IDEOne Demo

でありますよくあなたが捕獲されていないすべてのパターンを破棄し、あなたが持っている場合は、例えば、キャプチャしたいものに集中することができ廃棄技術、として知られている:

".*"|'.*'|`.*`|([^\W]+) 

これはすべて一致しますパターンが、conly最後の1

Regular expression visualization

+0

さて、私がやっているやり方は、https://ideone.com/4BdyeBのようなもので、出力に基づいて動作しません。回避策はありますか? – mttprvst13

+0

@ mttprvst13あなたは捕獲グループからコンテンツを取得しなければなりません。それはトリックである 'm.group(1)'を使ってください。私の答えでは、IDEOneのデモが動作することを確認することができます –

1

をキャプチャしますあなたが欲しいものを抽出するために、キャプチャグループを避け、使用することを希望する内容と一致する必要があります(私は他の方法があるとは思わない) 。これを行うのに便利なパターンは次のとおりです。

(?:[^\w"]+|"[^"]*")*+(\w+) 

各マッチでキャプチャグループ1の結果を返します。 demo

注:交換のためのパターンを使用したい場合は、キャプチャグループの最初の部分をあまりにも入れて、このグループを参照して、置換文字列を開始します。

((?:[^\w"]+|"[^"]*")*+)(\w+) 

他の方法、スプリットあなたが引用された部品や最終的な行方不明の終了引用符内のエスケープ引用符を処理するために"[^"]*""[^"\\]*+(?s:\\.[^"\\]*)*+"?に変更することができます(?:[^\w"]+|"[^"]*")+

:とあなたの文字列。

1

残念ながら私はまだ他の投稿にはコメントできませんが、複数の引用符があるとFederico Piazzaのソリューションは失敗します。それは代わりにパターン

Pattern ptrn = Pattern.compile("\".*?\"|([\\w]+)"); 

?を使用

test1 
test3 

を印刷して、完全にTEST2

をスキップするでしょう。この場合

String text = "test1 \"hello world!\" test2 \"foobar\" test3"; 

:たとえば、あなたのテキストは、次のことをした場合.*オペレーターは貪欲でなくても検索できます最後の引用ではなく次の引用。基本的に彼の答えをコピーするには、以下のことができます。

String text = "test1 \"hello world!\" test2 \"foobar\" test3"; 

Pattern ptrn = Pattern.compile("\".*?\"|([\\w]+)"); 
Matcher m = ptrn.matcher(text); 

while (m.find()) { 
    if (m.group(1) != null) { 
     System.out.println("Text: "+m.group(1)); 
    } 
} 
+0

欲張り対非貪欲編集の良いキャッチ。それは私の意味を完全に変えた不幸なタイプミスでした。 – gottfred

0

あなたは、末尾のスペースを除くと引用符の外の言葉たい:

[^"\s]++((?=\s*"[^\s])|(?=\s*$)|(?=[^"]+\s+")) 

Live demo

場合、それが失敗した:オープニング引用符の前にスペースはありません

  1. を。
  2. 引用符の前にスペースがあります。
  3. 入力内にネストされた引用符または不要な引用符があります。

したがって、OPの通常の入力でのみ定期的に動作します。

+0

ちょうど、 '(?<= \ b)'は '(?= \ b)'と同じですが '\ b'と同じです。 –

+0

あなたは良い点を出しましたが、それはまったく必要ではありません。私はそれを削除した。 @AlanMoore – revo

関連する問題