【问题标题】:Error on Pattern matching with subgroups - neither greedy nor ungreedy qualifiers work与子组匹配的模式出错 - 贪婪和不贪婪的限定符都不起作用
【发布时间】:2015-05-13 12:27:57
【问题描述】:

我正在尝试将文本和 word 文档中的前缀/后缀分开。这是一个 ZIP 文件,我参与其中 word/document.xml 看起来像

^.*<w:body> 
...this is the text... 
<w:sectPr[^>]*><some_selfclosing_tags/>*</w:sectPr>
</w:body>.*$

问题是我无法确定 Pattern 引擎放 可选

 <w:sectPr>...</<w:sectPr> 

在带有&lt;/w:body&gt; 的后缀组中。 它既不适用于贪婪的?,也不适用于不贪婪的?? 限定符,如下所示:

Pattern.compile("^(.*<w:body[^>]*>)(.*)"
+"((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>)?"
+"\\s*</w:body\\s*>.*)$", Pattern.DOTALL)

Pattern.compile("^(.*<w:body[^>]*>)(.*)"
+"((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>)??"
+"\\s*</w:body\\s*>.*)$", Pattern.DOTALL)

这是问题的简化版本:

String doc="<?xml version=\"1.0\"><w:document><w:body> ...text... <w:sectPr><w:cols w:space=\"720\"/></w:sectPr></w:body></w:document>";
Pattern rxv[]=new Pattern[]
        {Pattern.compile("^(.*<w:body[^>]*>)(.*)" 
                        +"((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>)?" 
                        +"\\s*</w:body\\s*>.*)$", Pattern.DOTALL)
        ,Pattern.compile("^(.*<w:body[^>]*>)(.*)" 
                        +"((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>)??" 
                        +"\\s*</w:body\\s*>.*)$", Pattern.DOTALL)
        };
ApplStr.ckRx(doc, rxv); 

以上在 System.out 上产生:

rx0:^(.*<w:body[^>]*>)(.*)((?:w:sectPr[^>]*>\s*(?:<\w+[^/>]*/>\s*)*</w:sectPr\s*>)?\s*</w:body\s*>.*)$
rx0Grp0:
<?xml version="1.0"><w:document><w:body> ...text... <w:sectPr><w:cols w:space="720"/></w:sectPr></w:body></w:document>
rx0Grp1:
<?xml version="1.0"><w:document><w:body>
rx0Grp2:
 ...text... <w:sectPr><w:cols w:space="720"/></w:sectPr>
rx0Grp3:
</w:body></w:document>

rx1:^(.*<w:body[^>]*>)(.*)((?:<w:sectPr[^>]*>\s*(?:<\w+[^/>]*/>\s*)*</w:sectPr\s*>)??\s*</w:body\s*>.*)$
rx1Grp0:
<?xml version="1.0"><w:document><w:body> ...text... <w:sectPr><w:cols w:space="720"/></w:sectPr></w:body></w:document>
rx1Grp1:
<?xml version="1.0"><w:document><w:body>
rx1Grp2:
 ...text... <w:sectPr><w:cols w:space="720"/></w:sectPr>
rx1Grp3:
</w:body></w:document>

我想要的是&lt;w:sectPr&gt;&lt;w:cols w:space="720"/&gt;&lt;/w:sectPr&gt; 在第 3 组而不是第 2 组。

【问题讨论】:

  • 抱歉 - 我忘了使用 Ctrl-K 来作为内联代码引号。
  • 问题是我无法确定 Pattern 引擎将 optional 放在带有 .它既不适合贪婪?也不贪心??限定符如下所示:
  • 可选部分是...
  • 您考虑过使用 XML 解析器吗?
  • 如果您删除&lt;w:sectPr[^&gt;]*&gt;&lt;some_selfclosing_tags/&gt;*&lt;/w:sectPr&gt;,您的正则表达式仍将匹配该字符串。我看到的唯一问题是您在+"\s*&lt;/w:body 中的\s 之前缺少一个反斜杠。这能解决问题吗?

标签: regex regex-group regex-greedy


【解决方案1】:

为了捕获您需要作为第 2 组的一部分的子字符串,您需要在第 2 组中使用 .*? 的惰性匹配:

^(.*<w:body[^>]*>)(.*?)((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>‌)?\\s*</w:body\\s*>.*)$

这是IDEONE demo

String str = "<?xml version=\"1.0\"><w:document><w:body> ...text... <w:sectPr><w:cols w:space=\"720\"/></w:sectPr></w:body></w:document>";
String rx = "^(.*<w:body[^>]*>)(.*?)((?:<w:sectPr[^>]*>\\s*(?:<\\w+[^/>]*/>\\s*)*</w:sectPr\\s*>)?\\s*</w:body\\s*>.*)$";
Pattern ptrn = Pattern.compile(rx);
Matcher m = ptrn.matcher(str);
while (m.find()) {
    System.out.println(m.group(1));
    System.out.println(m.group(2));
    System.out.println(m.group(3));
}

输出:

<?xml version="1.0"><w:document><w:body>
 ...text... 
<w:sectPr><w:cols w:space="720"/></w:sectPr></w:body></w:document>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-07
    • 2012-11-17
    • 2017-10-16
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多