2009-06-25 12 views
0

二重括弧で囲まれた文字列を抽出しようとしています。たとえば、一致する必要がある[[これは1つのトークンです]]。物事をよりエレガントにするためには、\ [[このエスケープされたトークン\]]のような二重括弧で囲まれた項目がマッチしないように、エスケープシーケンスがなければなりません。Javaの正規表現が期待通りに機能しない

トークンを抽出する "グループ1"のパターン[^\\\\]([\\[]{2}.+[^\\\\][\\]]{2})は近いですが、動作しない状況があります。問題は、最初の "not"ステートメントが "バックスラッシュ以外のもの"として評価されているようです。問題は、「何か」に「何もない」が含まれていないことです。だから、このパターンを "バックスラッシュ以外の文字も何もない"と一致させるものは何でしょうか?ここで

は、目的の動作を示すためのユニットテストです:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
import junit.framework.TestCase; 

public class RegexSpike extends TestCase { 
    private String regex; 
    private Pattern pattern; 
    private Matcher matcher; 

    @Override 
    protected void setUp() throws Exception { 
     super.setUp(); 
     regex = "[^\\\\]([\\[]{2}.+[^\\\\][\\]]{2})"; 
     pattern = Pattern.compile(regex); 
    } 

    private String runRegex(String testString) { 
     matcher = pattern.matcher(testString); 
     return matcher.find() ? matcher.group(1) : "NOT FOUND"; 
    } 

    public void testBeginsWithTag_Passes() { 
     assertEquals("[[should work]]", runRegex("[[should work]]")); 
    } 

    public void testBeginsWithSpaces_Passes() { 
     assertEquals("[[should work]]", runRegex(" [[should work]]")); 
    } 

    public void testBeginsWithChars_Passes() { 
     assertEquals("[[should work]]", runRegex("anything here[[should 
work]]")); 
    } 

    public void testEndsWithChars_Passes() { 
     assertEquals("[[should work]]", runRegex("[[should 
work]]with anything here")); 
    } 

    public void testBeginsAndEndsWithChars_Passes() { 
     assertEquals("[[should work]]", runRegex("anything here[[should 
work]]and anything here")); 
    } 

    public void testFirstBracketsEscaped_Fails() { 
     assertEquals("NOT FOUND", runRegex("\\[[should NOT work]]")); 
    } 

    public void testSingleBrackets_Fails() { 
     assertEquals("NOT FOUND", runRegex("[should NOT work]")); 
    } 

    public void testSecondBracketsEscaped_Fails() { 
     assertEquals("NOT FOUND", runRegex("[[should NOT work\\]]")); 
    } 

} 
+0

何がNULLまたは空白を意味しないのでしょうか? – northpole

答えて

3

あなたは単に(^|[^\\])を使用することができ、その意志いずれか一致文字列の先頭(あなたが正規表現にMULTILINEモードを設定して)またはスペースを含むバックスラッシュ(ではない単一の文字を、改行など)。

また、そうでない場合は、このような"[[one]] and [[two]]"として文字列が"one]] and [[two"が括弧の間にあると考えられている単一のマッチとして見られることになるので、.+?.+を交換したいと思うでしょう。

第3の点は、[]の文字クラスで単一の文字(たとえば、\[または\]などのエスケープ文字も含む)をラップする必要がないという点です。

だから、(明確にするため、二重escapednessを削除する私を許し)は、次の正規表現になるだろう:

(^|[^\\])(\[{2}.+?[^\\]\]{2}) 

は(また、あなたがあなたの正規表現でエスケープ文字をエスケープすることはできませんのでご注意[の前に2つのスラッシュ。単一の(エスケープされた)スラッシュとして解析されませんが、単一の(エスケープされていない)スラッシュとエスケープされたブラケットを示します)。

1

あなたは(?<!expr)である「ゼロ幅の負の後読みアサーション」を、したいです。試す:

(?<!\\\\)([\\[]{2}.+[^\\\\][\\]]{2}) 

実際、これは簡略化し、それらの不要ブラケットの一部を切り出し、そしてあまりにも、閉鎖ブラケット用負後読みを追加することによって、より一般的にすることができます。 (文字列の途中にエスケープされた括弧があると、[[text\]]moretext]]のようにあなたのバージョンも失敗します)。

(?<!\\\\)(\\[{2}.*?(?<!\\\\)\\]{2}) 
1

この文字列はどうなりますか? (実際の文字列の内容、Javaはリテラルではありません。)私は聞いてるのよ何

foo\\[[blah]]bar 

あなたはエスケープバックスラッシュをサポートしているかどうかです。あなたがそうであれば、ルックバックはうまくいかないでしょう。単一のバックスラッシュを探すのではなく、奇妙ではあるが未知数のものをチェックしなければならず、Javaのlookbehindはそのように自由に終わることはできません。また、エスケープされたかっこについては、のトークンは有効ですか?すぐにトークンの一部として、第1ブラケットの前にエスケープ文字(すなわち、バックスラッシュを加えたもの)の任意の数と一致:いずれの場合で

foo[[blah\]]]bar 

は、私はあなたが他の方向からのバックスラッシュの問題に来る示唆しています。トークンの内部では、大括弧またはバックスラッシュ以外の任意の数の文字、または任意の数のエスケープ文字と一致します。

(?<!\\)(?:\\.)*+\[\[((?:[^\[\]\\]++|\\.)*+)\]\] 

...とここでは、Javaの文字列リテラルとしてである:ここでは、実際の正規表現だ

"(?<!\\\\)(?:\\\\.)*+\\[\\[((?:[^\\[\\]\\\\]++|\\\\.)*+)\\]\\]" 
関連する問題