Java正则表达式提取标签之间的文本


82

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

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

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

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

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


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

Answers:


184

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

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查找感兴趣的元素。有关更多信息,请参见Java XPath API


3
非常感谢,这正是我所需要的。我将研究XPath,但是目前我认为该解决方案可以工作。我的应用程序非常简单,可能会保持这种状态。再次感谢!
b10hazard 2011年

这个字符串"<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear"呢?我们怎样才能pear不结束标记?
K.Sopheak '17

概括地说:私有String extractDataFromTags(String tag){模式pattern = Pattern.compile(“ <。+?>(。+?)</.+?>”); Matcher matcher = pattern.matcher(tag); matcher.find(); 返回(matcher.group(1)); //打印要提取或引发异常的字符串}
PMateus '18

15

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

jTopas是一个AWESOME令牌生成器,可以很容易地手动编写解析器(我强烈建议在标准的Java扫描器/等库中使用jtopas)。如果您想了解实际的jtopas,这里有一些我使用jTopas编写的解析器,用于解析这种类型的文件

如果要解析XML文件,则应该使用xml解析器库。除非您只是为了娱乐而做,否则不要自己做,那里有很多行之有效的选择


谢谢你的建议。我已经为它们添加了书签,我肯定会在以后的项目中使用它。目前,正则表达式方法可能是我将要使用的方法,因为要解析的文件非常小/简单。
b10hazard 2011年

7

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

    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));
        }
    }

如果存在一系列不同的标签或嵌套标签(例如<h2>Mac</h2><h1>loves it</h1>或),则模式将是什么<h2>Mac<h1>liked your answer</h1></h2>
MAC

1
请编辑我<matcher.groupCount(); 到我<= matcher.groupCount(); 包括第一个匹配的子字符串,即 在第0个索引处
AVA

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%


2
    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));

标签前缀如何处理(如果前缀是动态的)
user1514499 '19

2
    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++;
        }

1

我在此回复前加上“您不应该使用正则表达式来解析XML-只会导致无法正常工作的极端情况,以及试图修复它时导致复杂性不断增加的正则表达式。”

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

if (m.matches())
{
   String result = m.group(1);
   // do something with result
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.