【问题标题】:Java regex to extract text between tagsJava正则表达式提取标签之间的文本
【发布时间】:2011-09-27 11:43:55
【问题描述】:

我有一个包含一些自定义标签的文件,我想编写一个正则表达式来提取标签之间的字符串。例如,如果我的标签是:

[customtag]String I want to extract[/customtag]

我将如何编写一个正则表达式来仅提取标签之间的字符串。这段代码似乎是朝着正确方向迈出的一步:

Pattern p = Pattern.compile("[customtag](.+?)[/customtag]");
Matcher m = p.matcher("[customtag]String I want to extract[/customtag]");

不知道下一步该做什么。有任何想法吗?谢谢。

【问题讨论】:

  • 对于初学者,您需要转义 [] 方括号,它们是正则表达式中的元字符。

标签: java regex


【解决方案1】:

你在正确的轨道上。现在你只需要提取所需的组,如下:

final Pattern pattern = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);
final Matcher matcher = pattern.matcher("<tag>String I want to extract</tag>");
matcher.find();
System.out.println(matcher.group(1)); // Prints String I want to extract

如果你想提取多个匹配,试试这个:

public static void main(String[] args) {
    final String str = "<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear</tag>";
    System.out.println(Arrays.toString(getTagValues(str).toArray())); // Prints [apple, orange, pear]
}

private static final Pattern TAG_REGEX = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);

private static List<String> getTagValues(final String str) {
    final List<String> tagValues = new ArrayList<String>();
    final Matcher matcher = TAG_REGEX.matcher(str);
    while (matcher.find()) {
        tagValues.add(matcher.group(1));
    }
    return tagValues;
}

但是,我同意正则表达式不是这里的最佳答案。我会使用 XPath 来查找我感兴趣的元素。有关详细信息,请参阅 The Java XPath API

【讨论】:

  • 非常感谢,这正是我所需要的。我将研究 XPaths,但现在我认为这个解决方案会起作用。我的应用程序非常简单,并且可能会保持这种状态。再次感谢!
  • 这个字符串"&lt;tag&gt;apple&lt;/tag&gt;&lt;b&gt;hello&lt;/b&gt;&lt;tag&gt;orange&lt;/tag&gt;&lt;tag&gt;pear"怎么样?我们如何在没有关闭标签的情况下获得pear
  • 概括:private String extractDataFromTags(String tag) { Pattern pattern = Pattern.compile("<.>(.+?)+?>");匹配器 matcher = pattern.matcher(tag); matcher.find();返回(matcher.group(1)); // 打印我要提取的字符串或抛出异常 }
【解决方案2】:

说实话,正则表达式并不是这种解析的最佳方法。您发布的正则表达式可能适用于简单的情况,但如果事情变得更复杂,您将遇到巨大的问题(与您无法使用正则表达式可靠地解析 HTML 的原因相同)。我知道你可能不想听到这个,我知道当我问相同类型的问题时我不想听到,但是在我停止尝试对所有内容使用正则表达式后,字符串解析对我来说变得更加可靠。

jTopas 是一个很棒的分词器,可以很容易地手动编写解析器(我强烈建议使用 jtopas,而不是标准的 java 扫描器/etc.. 库)。如果您想查看 jtopas 的运行情况,here 是我使用 jTopas 编写的一些解析器来解析 this 类型的文件

如果您正在解析 XML 文件,您应该使用 xml 解析器库。除非您只是为了好玩,否则不要自己做,那里有很多经过验证的选择

【讨论】:

  • 感谢您的建议。我已经为它们添加了书签,我肯定会考虑在未来的项目中使用它。现在正则表达式方法可能是我要使用的方法,因为我正在解析的文件非常小/简单。
【解决方案3】:

一种查找标签、属性和值的通用、更简单且有点原始的方法

    Pattern pattern = Pattern.compile("<(\\w+)( +.+)*>((.*))</\\1>");
    System.out.println(pattern.matcher("<asd> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd TEST</asd>").find());
    System.out.println(pattern.matcher("<asd attr='3'> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd> <x>TEST<x>asd>").find());
    System.out.println("-------");
    Matcher matcher = pattern.matcher("<as x> TEST</as>");
    if (matcher.find()) {
        for (int i = 0; i <= matcher.groupCount(); i++) {
            System.out.println(i + ":" + matcher.group(i));
        }
    }

【讨论】:

  • 如果有一系列不同的标签或嵌套标签,如&lt;h2&gt;Mac&lt;/h2&gt;&lt;h1&gt;loves it&lt;/h1&gt;&lt;h2&gt;Mac&lt;h1&gt;liked your answer&lt;/h1&gt;&lt;/h2&gt;,模式会是什么?
  • 请编辑 i
【解决方案4】:

试试这个:

Pattern p = Pattern.compile(?<=\\<(any_tag)\\>)(\\s*.*\\s*)(?=\\<\\/(any_tag)\\>);
Matcher m = p.matcher(anyString);

例如:

String str = "<TR> <TD>1Q Ene</TD> <TD>3.08%</TD> </TR>";
Pattern p = Pattern.compile("(?<=\\<TD\\>)(\\s*.*\\s*)(?=\\<\\/TD\\>)");
Matcher m = p.matcher(str);
while(m.find()){
   Log.e("Regex"," Regex result: " + m.group())       
}

输出:

10 恩

3.08%

【讨论】:

    【解决方案5】:
        String s = "<B><G>Test</G></B><C>Test1</C>";
    
        String pattern ="\\<(.+)\\>([^\\<\\>]+)\\<\\/\\1\\>";
    
           int count = 0;
    
            Pattern p = Pattern.compile(pattern);
            Matcher m =  p.matcher(s);
            while(m.find())
            {
                System.out.println(m.group(2));
                count++;
            }
    

    【讨论】:

      【解决方案6】:
          final Pattern pattern = Pattern.compile("tag\\](.+?)\\[/tag");
          final Matcher matcher = pattern.matcher("[tag]String I want to extract[/tag]");
          matcher.find();
          System.out.println(matcher.group(1));
      

      【讨论】:

      • 标签的前缀怎么样(如果前缀是动态的)
      【解决方案7】:

      我在这个回复前加上“你不应该使用正则表达式来解析 XML ——它只会导致无法正常工作的边缘情况,以及在你尝试的时候永远增加复杂性的正则表达式修复它。”

      话虽如此,您需要继续匹配字符串并获取所需的组:

      if (m.matches())
      {
         String result = m.group(1);
         // do something with result
      }
      

      【讨论】: