二重引用符で囲まれたテキストを選択する必要があり、二重引用符の数は 2 または 0 で割り切れる必要があります。入力例:
Starting
blahaapvi "Starting + Ending"
asfg "Ending"
Ending
私は今これを持っています: Starting(.*)Ending
...しかし、引用符で囲まれたテキストを一致させたくありません。誰でも私を助けてください。
これを試して、二重引用符のバランスが取れているテキストを見つけてください
^Starting([^"]*"(?<txt>[^"]*)"[^"]*)*Ending$
これが説明です
^Starting
テキストの冒頭のパターン。
[^"]*
二重引用符を含まない任意の数の文字。
"(?<txt>[^"]*)"
「txt」という名前のキャプチャでキャプチャされた二重引用符に含まれるテキスト。
[^"]*
ここでも、二重引用符を含まない任意の数の文字。
(...)*
二重引用符で囲まれたテキストを含む可能性のあるテキストの繰り返し。
Ending$
テキストの最後のパターン。
これを試して
(テキスト内で改行できるように編集されています)
static void Main(string[] args) {
string l_input1 = "match \"text\" with \r\n even \"quotes\"";
string l_input2 = "unmatch \"text\" with \r\n uneven quotes\"";
string l_pattern = @"^(?>([^""]*?((?<QUOTE>"")[^""]*(?<-QUOTE>"")?))*)$(?(QUOTE)(?!))";
bool l_isMatch1 = Regex.IsMatch( l_input1, l_pattern );
bool l_isMatch2 = Regex.IsMatch( l_input2, l_pattern );
Console.WriteLine( l_isMatch1 );
Console.WriteLine( l_isMatch2 );
Console.ReadKey( true );
}
説明:
^(?>([^"]*?((?<QUOTE>")[^"]*(?<-QUOTE>")?))*)$(?(QUOTE)(?!))
これは、入力の先頭 (^) から末尾 ($) までの一致を試み、最後の奇数の二重引用符の後のテキストを無視することを防ぎます。
基本的な考え方は、QUOTE 名前付きグループ スタックを 1 一致と 0 一致の間で切り替えることです。したがって、正規表現は、0 個以上の二重引用符以外の文字 ([^"]*?) に一致することから始まります。二重引用符が見つかった場合は、それを名前付きグループ (「QUOTE」という名前) スタックに追加し、0 の一致を続行します。 2 つ目の二重引用符が見つかった場合は、"QUOTE" スタックに追加された最後の一致を削除し (したがって、スタックには 0 件の一致が含まれます)、最初に戻ります。
文字列の終わりの後に、条件付きグルーパーがあります。条件は、名前付きグループ「QUOTES」に 1 つ以上の一致が追加された場合、ゼロ長の否定先読みを実行することです (常に正規表現が失敗します)。これにより、2 番目の引用符が見つからなかった場合 (つまり "QUOTES" スタックがクリアされた場合)、正規表現全体が失敗することが保証されます。
編集:
引用されたテキストを実際にキャプチャしたい場合は、これを使用します。
static void Main(string[] args) {
string l_input1 = "match \"text\" with \r\n even \"quotes\"";
string l_input2 = "unmatch \"text\" with \r\n uneven quotes\"";
string l_pattern = @"^(?>([^""]*?(?<QUOTED_TEXT>(?<QUOTE>"")[^""]*(?<-QUOTE>"")?))*)$(?(QUOTE)(?!))";
Match l_match1 = Regex.Match( l_input1, l_pattern );
Match l_match2 = Regex.Match( l_input2, l_pattern );
Console.WriteLine( l_match1.Success );
foreach ( Capture l_quotedText in l_match1.Groups["QUOTED_TEXT"].Captures ) {
Console.WriteLine( l_quotedText.Value );
}
Console.WriteLine( l_match2.Success );
Console.ReadKey( true );
}
}