【问题标题】:Java - how to match regex Pattern containing single quotes?Java - 如何匹配包含单引号的正则表达式模式?
【发布时间】:2010-11-01 00:59:48
【问题描述】:

[已编辑 - 真的很抱歉,我引用的代码是错误的 - 已更改以下消息以反映这一点。道歉!感谢您的耐心等待。]

我是正则表达式的新手,想在 Java 中匹配一个模式(接着这个解决方案 - Java string - get everything between (but not including) two regular expressions?)。

字符串是[EDITED]:

<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row>

我只想返回 column name='text' 标签之间的内容,所以:

Header\n\n\ntext

我有 [EDITED] 下面的代码,但它不匹配。关于我需要如何更改模式的任何想法?

谢谢!

package test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex {

    public static void main(String[] args) {
        Pattern p = Pattern.compile(
                "<row><column name='text'>(.*)</column></row>",
                Pattern.DOTALL
            );
        Matcher matcher = p.matcher(
                "<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row>"
            );
        if(matcher.matches()){
                System.out.println(matcher.group(1));
        }
    }
}

【问题讨论】:

    标签: java regex string


    【解决方案1】:

    您的问题与引号字符无关。您只需要切换到非贪婪量词(正如其他人建议的那样)并使用find() 方法而不是matches()

    public static void main(String[] args)
    {
      Pattern p = Pattern.compile(
          "<row><column name='text'>(.*?)</column></row>",
          Pattern.DOTALL
      );
    
      Matcher matcher = p.matcher(
          "<row><column name='_id'>1</column></row>" +
          "<row><column name='text'>Header\n\n\ntext</column></row>" +
          "<row><column name='pwd'>password</column></row>"
      );
    
      if(matcher.find()) {
          System.out.println(matcher.group(1));
      }
    }
    

    matches() 仅当正则表达式从目标字符串的开头匹配到结尾时才返回true。如果要匹配少于整个字符串的任何内容,则需要使用find()

    【讨论】:

      【解决方案2】:

      您发布的(未经编辑的)代码对我来说很好用...它匹配并打印出您期望的消息。

      编辑后的代码不起作用,但是如果您将正则表达式稍微更改为如下所示:

      Pattern p = Pattern.compile(
                  ".*<row><column name='text'>(.*)</column></row>.*",
                  Pattern.DOTALL
              );
      

      你得到一个匹配:

      Header
      
      
      text</column></row><row><column name='pwd'>password
      

      这可能不是您真正想要的,因此您需要进一步完善正则表达式。使用正则表达式来处理 xml/html 解析通常不是一个好方法。 Yishai 建议使用 XML 解析器是一种更好的方法,否则您很可能会得到一个极其复杂且不灵活的正则表达式。

      【讨论】:

      • 谢谢!感谢您的建议 - 我会考虑使用 XML 解析器。
      【解决方案3】:

      也许你真正想要达到的是:

      public static void main(String[] args) {
          Pattern p = Pattern.compile(
                  "<row><column name='(.*?)'>(.*?)</column></row>",
                  Pattern.DOTALL
              );
      
          Matcher matcher = p.matcher(
                  "<row><column name='text'>Header\n\n\ntext</column></row>"
              );
      
          if(matcher.matches()){
                  System.out.println(matcher.group(2));
          }
      }
      

      因为您的真实示例可以在 name= 值中包含任何内容(至少这看起来更真实)。

      话虽如此,如果这变得更加重要,您可能希望将其视为 SAX 解析器(内置于 JDK 1.5+,因此不一定是库依赖问题)。如果您真的不太关心文档结构并且只想从中吸取一些琐碎的东西,那么正则表达式是解析 XML 的更好方法。但是,如果您开始研究属性并关心它们在 XML 上的含义,那么继续沿着正则表达式路线走下去就是在重新发明轮子。

      【讨论】:

        【解决方案4】:

        尝试匹配(.*?) 而不仅仅是(.*)

        (.*) 是一个贪婪搜索,它会匹配它之后的所有内容。

        (.*?) 将在第一次出现“&lt;/column&gt;&lt;/row&gt;”时停止。

        编辑:这应该不会真正影响您的示例,但如果字符串中有另一个“&lt;/column&gt;&lt;/row&gt;”,那么您的模式将不会像您预期的那样匹配。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-16
          • 1970-01-01
          • 1970-01-01
          • 2020-01-14
          • 1970-01-01
          • 2014-01-25
          • 1970-01-01
          • 2016-04-24
          相关资源
          最近更新 更多