我需要选择带有双引号的文本,并且双引号的数量必须可以被 2 或零整除。示例输入:
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)(?!))
这将尝试从输入的开头 (^) 到结尾 ($) 进行匹配,以防止它忽略最后一个奇数双引号之后的文本。
基本思想是在 1 匹配和 0 匹配之间切换 QUOTE 命名组堆栈。因此,正则表达式将从匹配 0 个或多个非双引号字符 ([^"]*?) 开始。如果找到双引号,则将其添加到命名组(名为“QUOTE”)堆栈并继续匹配 0或更多非双引号字符。如果找到第二个双引号,则删除添加到“QUOTE”堆栈的最后一个匹配项(因此堆栈将包含 0 个匹配项),然后重复回到开头。
在字符串的末尾,有一个条件分组。条件是,如果已将 1 个或多个匹配项添加到命名组“QUOTES”,则执行零长度负前瞻(这将始终导致正则表达式失败)。这将确保,如果没有找到第二个引号(从而清除“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 );
}
}