正则表达式:不是任意的非捕获组
我试图写正则表达式来覆盖我所有的情况。 我必须解析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