如何选择首选(但特定)正则表达式匹配超过默认(但通用)一个

本文关键字:默认 一个 选择 何选择 正则表达式 | 更新日期: 2023-09-27 18:15:33

我试图捕获文本块的各个部分,包括它是否具有开始或结束引号,然后文本块本身,不包括那些引号。当我只有一个结束引号,句号和结束引号或者只有一个结束引号时,Regex模式工作得很好。

        string test = @"""This has a begin quote, period and end quote.""" + Environment.NewLine +
                      @"""This has a begin quote and period." + Environment.NewLine +
                      @"""This has a begin quote and end quote""" + Environment.NewLine +
                      @"""This has a begin quote only" + Environment.NewLine;
        string pattern = @"^'s*(?<BeginQuote>"")?" +
            @"(?<BodyPattern>.+(('.(?=""?'s*$))|(?=""'s*$)))" +
            @"(?<EndQuote>""(?='s*$))?";
        Regex rx = new Regex(pattern, RegexOptions.Multiline);
        MatchCollection matches = rx.Matches(test);
        foreach (Match m in matches)
        {
            GroupCollection groups = m.Groups;
            Console.WriteLine("Beginning Quotation Mark:  {0}", groups["BeginQuote"].Success);
            Console.WriteLine("BodyPattern:  {0}", groups["BodyPattern"]);
            Console.WriteLine("Ending Quotation Mark:  {0}", groups["EndQuote"].Success);
        }

输出如下:
起始引号:True
bodyppattern:这有一个开始引号,句号和结束引号。
结束引号:True

起始引号:True
bodyppattern:它有一个起始引号和句号。
结束引号:False

起始引号:True
bodyppattern:这有一个开始引号和结束引号
结束引号:True

问题是当我试图为既没有结束引号也没有句号的情况提供匹配时。我尝试了多种变化来捕捉字符串的结束。这总是有效的,但最终也会捕获任何结束引用。如果其他测试不起作用,我如何使此选项成为"后备"选项?

下面是我在Regex模式中尝试的一种变体:

        string pattern = @"^'s*(?<BeginQuote>"")?" +
            @"(?<BodyPattern>.+(('.(?=""?'s*$))|(?=""'s*$)|($)))" +
            @"(?<EndQuote>""(?='s*$))?";

然而,此模式始终默认为字符串结束选项:

起始引号:True
bodyppattern:它有一个开始引号,句号和结束引号。"
结束引号:False

起始引号:True
bodyppattern:它有一个起始引号和句号。
结束引号:False

起始引号:True
bodyppattern:这有一个开始引号和结束引号"
结束引号:False

起始引号:True
bodyppattern:这个只有一个起始引号
结束引号:False

我还尝试将字符串结束选项作为第一选择(相同的输出;并试图使该表达式"懒惰"(但我使用"??"进行的几次尝试产生了相同的输出)。我还尝试了对可选方案的各种分组(虽然可能不是所有的可能性),但输出结果相同。

如何选择首选(但特定)正则表达式匹配超过默认(但通用)一个

+量词贪心,用+?代替。这应该能成功。

string test = @"""This has a begin quote, period and end quote.""" + "'n" +
              @"""This has a begin quote and period." + "'n" +
              @"""This has a begin quote and end quote""" + "'n" +
              @"""This has a begin quote only";
Regex rx = new Regex(@"(?m)^'s*(?<BeginQuote>"")?(?<BodyPattern>.+?(?:'.|(?=""|$)))(?<EndQuote>"")?");
foreach (Match m in rx.Matches(test)) {
   Console.WriteLine("Beginning Quotation Mark: {0}", m.Groups["BeginQuote"].Success);
   Console.WriteLine("BodyPattern: {0}", m.Groups["BodyPattern"]);
   Console.WriteLine("Ending Quotation Mark: {0}", m.Groups["EndQuote"].Success);
   Console.WriteLine("--------------------------");
}

输出
Beginning Quotation Mark: True
BodyPattern: This has a begin quote, period and end quote.
Ending Quotation Mark: True
--------------------------
Beginning Quotation Mark: True
BodyPattern: This has a begin quote and period.
Ending Quotation Mark: False
--------------------------
Beginning Quotation Mark: True
BodyPattern: This has a begin quote and end quote
Ending Quotation Mark: True
--------------------------
Beginning Quotation Mark: True
BodyPattern: This has a begin quote only
Ending Quotation Mark: False
--------------------------

我把hwnd的答案标记为正确,因为它给了我如何使用惰性量词的线索。但是,我使用了我的代码,因为每当您向文本添加内部引号或添加额外的空白时,Regex都会失败。我修改了测试文本,使其更易于阅读。下面是我最终使用的:

        string test = "'"This has a begin quote, '"period'" and end quote.'t  '"'n  " +
                      "'"This has a begin quote and period.'n" +
                      "This has no begin quote but an end quote'"'n" +
                      "'"This has a '"begin'" quote only   'n" ;
        string pattern = @"^'s*(?<BeginQuote>"")?" +
            @"(?<BodyPattern>.+?(('.(?=""?'s*$))|(?=""'s*$)|($)))" +
            @"(?<EndQuote>""(?='s*$))?";
        Regex rx = new Regex(pattern, RegexOptions.Multiline);
        MatchCollection matches = rx.Matches(test);

输出:起始引号:True
bodyppattern:它有一个开始引号,"句号"和结束引号。
结束引号:True

起始引号:True
bodyppattern:它有一个起始引号和句号。
结束引号:False

起始引号:False
bodyppattern:没有开始引号,只有结束引号
结束引号:True

起始引号:True
BodyPattern:只有一个"begin"引号
结束引号:False