タグ間のテキストを抽出する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 2011

回答:


186

あなたは正しい方向に進んでいます。次に、次のように、目的のグループを抽出する必要があります。

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 XPathAPIを参照してください。


3
どうもありがとう、それは私が必要としていたものです。XPathについて調べますが、今のところ、このソリューションは機能すると思います。私のアプリケーションは非常にシンプルで、おそらくそのままです。再度、感謝します!
b10hazard 2011

この文字列は"<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear"どうですか?どうすれpearばクローズタグなしで取得できますか?
K.Sopheak 2017

一般化するには:private String extractDataFromTags(String tag){Pattern pattern = Pattern.compile( "<。+?>(。+?)</。+?>"); マッチャーマッチャー= pattern.matcher(tag); matcher.find(); return(matcher.group(1)); //抽出したい文字列を出力するか例外をスローします}
PMateus 2018

15

正直なところ、このタイプの構文解析では正規表現は最善の方法ではありません。投稿した正規表現は、単純な場合にはおそらくうまく機能しますが、事態がより複雑になると、大きな問題が発生します(正規表現でHTMLを確実に解析できないのと同じ理由)。おそらくこれを聞きたくないと思います。同じ種類の質問をしたときは聞きたくありませんでしたが、すべてに正規表現を使用するのをやめた後、文字列の解析の信頼性が大幅に向上しました。

jTopasは、パーサーを手動で非常に簡単に作成できる優れたトークナイザーです(標準の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
i <matcher.groupCount();を編集してください。to i <= 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));

タグのプレフィックスはどう
ですか

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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.