正则表达式:不是任意的非捕获组

我试图写正则表达式来覆盖我所有的情况。 我必须解析Xml并捕获一些属性。 例:

<item p2="2"/>
<item p1="1" p2="2"/>
<item p1="1" p2="2" p3="3"/>
<item p1="1" p2="2" p3="3" p4="4"/>
<item p1="1" p2="2" p3="3" p4="4" p5="5"/>

我必须捕捉“p2”属性的值,并且我知道“p2”将始终符合要求。 此外,我想捕捉并不总是存在的“p4”属性的值。

起初,我试图满足前四个例子(例子中的前4行),并且我写了这样的正则表达式:

<item.+?p2="(?<val1>d+)".*?(?:p4="(?<val2>d+)")?/>

它工作正常。 “val1”组总是返回值。 如果显示“p4”属性,“val2”组返回值。

但是为了掩饰我最后的情况:

<item p1="1" p2="2" p3="3" p4="4" p5="5"/>

我修改了我的正则表达式,如下所示:

<item.+?p2="(?<val1>d+)".*?(?:p4="(?<val2>d+)")?.*?/>
______________________________________________________^^^

我发现“val1”组仍然会返回值,但“val2”组不会返回所有情况下的值。

你能告诉我我错过了什么,并帮助写正则表达式来涵盖我所有的情况吗?

示例在这里正则表达式测试


XML不是常规语言,因此使用正则表达式不是要走的路。 你还需要一个解析器。

有很多方法可以做到这一点,但是我个人会将XML文档加载到XmlDocument类中,并使用SelectNodes方法和XPath查询来查找项目列表。 一旦你有了,你可以在每个找到的XmlNode上使用foreach,并使用Attributes集合来获取你想要的数据。

如果你必须使用正则表达式来做这件事,那么你需要做的就是放下最后一个。 在非捕获组内。 你所做的是给Regex权限来省略p4补丁和匹配。 代替。 通过把。*? 在组内部它消除了这种可能性。 这可能很慢(它甚至可能遭受灾难性的回溯),并且不能处理XML的所有复杂性。 这是一个演示的程序:

using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main()
    {
        var regex = new Regex(@"
        <item                  # Capture <item
        .+?                     # Capture one or more characters as few times as possible 
        p2=                     # Capture p2=
        ""                     # Capture opening quote
        (?<val1>d+)            # Capture one or more decimal digits and put them in val1
        ""                      # Capture closing quote
        .*?                     # Capture zero or more characters as few times as possible
        (?:                     # Begin a non capturing group
            p4=                 # Capture p4=
            ""                 # Capture opening quote
            (?<val2>d+)        # Capture one or more decimal digits and put them in val2
            ""                 # Capture closing quote
            .*?                 # Capture zero or more characters as few times as possible
        )?                      # Capture 0 or 1 p4s        
        />                      # Capture >
        ", RegexOptions.IgnorePatternWhitespace);

        Test(regex, @"<item p2=""2""/>", "2", string.Empty);
        Test(regex, @"<item p1=""1"" p2=""2""/>", "2", string.Empty);
        Test(regex, @"<item p1=""1"" p2=""2"" p3=""3""/>", "2", string.Empty);
        Test(regex, @"<item p1=""1"" p2=""2"" p3=""3"" p4=""4""/>", "2", "4");
        Test(regex, @"<item p1=""1"" p2=""2"" p3=""3"" p4=""4"" p5=""5""/>", "2", "4");
    }

    static void Test(Regex regex, string test, string p2, string p4)
    {
        Match m = regex.Match(test);

        string p2Group = m.Groups["val1"].Value;
        string p4Group = m.Groups["val2"].Value;

        Console.WriteLine("Test: '{0}'", test);
        Console.WriteLine("p2: '{0}' - {1}", p2Group, p2Group == p2 ? "Success" : "Fail");
        Console.WriteLine("p4: '{0}' - {1}", p4Group, p4Group == p4 ? "Success" : "Fail");
    }
}
链接地址: http://www.djcxy.com/p/74789.html

上一篇: Regex: not arbitrary non capturing group

下一篇: Confused about Matcher group in Java regex