2011-03-02 13 views
0

私は以下のパターンがあります。ここでは正規表現の問題(のC#で)

private static Regex rgxDefinitionDoMatch = new Regex(@"d:(?<value>(?:(?!c:|d:|p:).)+)", RegexOptions.Compiled); 
private static Regex rgxDefinitionDontMatch = new Regex(@"\!d:(?<value>(?:(?!c:|d:|p:).)+)", RegexOptions.Compiled); 
private static Regex rgxDefinitionExactDoMatch = new Regex(@"d:(?<value>\""(?:(?!c:|d:|p:).)+)\""", RegexOptions.Compiled); 
private static Regex rgxDefinitionExactDontMatch = new Regex(@"\!d:(?<value>\""(?:(?!c:|d:|p:).)+)\""", RegexOptions.Compiled); 

が一致する例の文字列です:今ここに

c:matchThis !c:dontMatchThis p:matchThis !p:dontMatchThis d:def !d:defDont d:"def" !d:"defDont" 

は、いくつかの問題があります:

  1. 私はrgxDefinitionDontMatchを使用して、両方を取得します!d:defDontd:"defDont"
  2. 私がrgxDefinitionDoMatchを使用するとさらに悪いです... !d:defDont,d:"defDont"!d:defおよびd:"def"が得られます。数2の場合

、私は、例えばrgxDefinitionDoMatch ^(?!\!)の前に感嘆符を無視するようにさまざまな組み合わせを試してみましたが、それは、ただ何も一致していません。私は何をすべきか分からない。

また、私は両方の問題1.と2.

のための引用符を無視する方法が必要になります誰が助けることはできますか?私はしばらくの間試してきました。

+0

[^ \!] d :(?(?:(?! c:| d:| p:| \!)))+) - これは感嘆符を無視するためのトリックを行うようですが、値は、私がチェックしているテキストの冒頭にntoです。テキストの先頭にd:testがあると、一致しません。開始以外のどこかにのみ一致します。何か案は? – Matt

答えて

2

これはあなたが探しているものですか?

Regex[] rgxs = { 
    new Regex(@"(?<!\S)d:(?:""(?<value>[^""]+)""|(?<value>\S+))"), 
    new Regex(@"(?<!\S)!d:(?:""(?<value>[^""]+)""|(?<value>\S+))") 
}; 

string input = @"c:matchThis !c:dontMatchThis p:matchThis !p:dontMatchThis d:def !d:defDont d:""def"" !d:""defDont"""; 

foreach (Regex r in rgxs) 
{ 
    Console.WriteLine(r.ToString()); 
    foreach (Match m in r.Matches(input)) 
    { 
    foreach (String name in r.GetGroupNames()) 
    { 
     Console.WriteLine("{0,-6} => {1}", name, m.Groups[name].Value); 
    } 
    } 
    Console.WriteLine(); 
} 
(?<!\S)d:(?:"(?<value>[^"]+)"|(?<value>\S+)) 
0  => d:def 
value => def 
0  => d:"def" 
value => def 

(?<!\S)!d:(?:"(?<value>[^"]+)"|(?<value>\S+)) 
0  => !d:defDont 
value => defDont 
0  => !d:"defDont" 
value => defDont

私はあなたが求めていたかを把握しようとしていたとして、私は最終的に最も簡単なコースでは、私のコードを投稿し、あなたのフィードバックを得ることだったことを決めました。私は必要に応じてそれを洗練し、(もちろん)それを説明しようとします。 :D


編集:ここでは、コメントでを求めた別の正規表現です:

Regex[] rgxs = { 
    new Regex(@"(?<!\S)d:(?<value>\S+)"), 
    new Regex(@"(?<!\S)!d:(?<value>\S+)"), 
    new Regex(@"(?<!\S)d:""(?<value>[^""]+)"""), 
    new Regex(@"(?<!\S)!d:""(?<value>[^""]+)""") 
}; 

は彼らに私が行った方法を組み合わせることは、「値」の部分が引用されている場合、それは問題ではありませんかそうでなければ、それはまだ取り込まれています。 (私はあなたが「引用符を無視する」という意味だと思っていました)。結合された形式について興味深いのは、同じ正規表現で同じグループ名を使用する方法です。

(?<!\S)は、空白以外の文字のネガティブなビヘイビアであり、あなたのコメントに疑問を投げかけます。すべての一致が文字列の先頭か空白文字のどちらかで始まるようにします。同様に、\S+は、一致が文字列の最後または次の空白文字の前にの末尾にあることを保証します。

"[^"]+"は、明らかに、引用符で囲まれたものに一致しますが、他の引用符は除きます。値に空白を含めることができます。これは、別々の正規表現の理由だと私は推測しました。しかし、私は主に引用符をエスケープするためにバックスラッシュを使用する必要はないことを指摘したいと思っていました。 C#の逐語的な文字列では、エスケープする余分な引用符:@"""[^""]+"""です。

+0

それは素晴らしいです!今度は、必要なのは、それらを2つの正規表現に分割することです:2つは引用符と一致させ、2つは引用符を伴いません:1.引用符+感嘆符、2:感嘆符なしの引用符、3:引用符のない+感嘆符および4.一致引用なしと感嘆符なし。それできますか?ありがとう! – Matt

+0

ありがとうアラン。私はもう一つ質問がありますが、あなたはすでにそれほど助けてくれたので、とにかく答えとしてマークします。唯一のことは、どのものが引用符を持っているかを判断することです。上記のEDITの下の2つの正規表現は、引用符で囲まれた文字列とのマッチングのためにはうまく動作しますが、トップ2は引用符で囲まれていません。引用符で囲まれていないものだけを返す必要があります。これは簡単だろうか?助けてくれてありがとう。 :-) – Matt

+0

ああ、以下のトリックをしているようだ: (?<!\ S)!d:(? \ S +) 私はanythignを見たことがありません。あなたはこれに関する問題を認識していますか? – Matt