web-dev-qa-db-fra.com

Java regex pour extraire le texte entre les balises

J'ai un fichier avec des balises personnalisées et j'aimerais écrire une expression régulière pour extraire la chaîne entre les balises. Par exemple si mon tag est:

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

Comment pourrais-je écrire une expression régulière pour extraire uniquement la chaîne entre les balises. Ce code semble être un pas dans la bonne direction:

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

Vous ne savez pas que faire ensuite. Des idées? Merci.

72
b10hazard

Vous êtes sur la bonne voie. Maintenant, il vous suffit d'extraire le groupe souhaité, comme suit:

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

Si vous voulez extraire plusieurs hits, essayez ceci:

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

Cependant, je conviens que les expressions régulières ne sont pas la meilleure réponse ici. J'utiliserais XPath pour trouver les éléments qui m'intéressent. Voir La Java XPath) pour plus d'informations.

158
hoipolloi

Pour être tout à fait honnête, les expressions régulières ne sont pas la meilleure idée pour ce type d'analyse. L'expression régulière que vous avez postée fonctionnera probablement très bien pour les cas simples, mais si la situation devient plus complexe, vous aurez d'énormes problèmes (même raison pour laquelle vous ne pouvez pas analyser de manière fiable le HTML avec des expressions régulières). Je sais que vous ne voulez probablement pas entendre cela, je le savais pas quand j'ai posé le même type de questions, mais l'analyse syntaxique est devenue beaucoup plus fiable pour moi après avoir cessé d'essayer d'utiliser des expressions régulières pour tout.

jTopas est un tokenizer IMPRESSIONNANT qui facilite l'écriture manuelle des analyseurs (je suggère FORTEMENT les jtopas aux bibliothèques standard Java scanner/etc ..). Si vous veux voir jtopas en action, ici certains analyseurs que j'ai écrits en utilisant jTopas pour analyser this type de fichier

Si vous analysez des fichiers XML, vous devriez utiliser une bibliothèque d'analyseur XML. Ne le faites pas vous-même à moins que vous ne le faisiez que pour le plaisir, il existe de nombreuses options éprouvées

10
jdc0589

Une approche générique, simple et primitive pour trouver une balise, un attribut et une valeur

    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));
        }
    }
6
Gorky
    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
Bibhuti Agarwal

Essaye ça:

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

Par exemple:

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

Sortie:

10 ene

3,08%

2
Heriberto Rivera

Je préfixe cette réponse par "vous ne devriez pas utiliser une expression régulière pour analyser XML - cela ne fera que résulter en des cas Edge qui ne fonctionneront pas correctement et en une regex de complexité de plus en plus complexe pendant que vous essayez de résoudre ce problème." . "

Cela étant dit, vous devez procéder en faisant correspondre la chaîne et en saisissant le groupe souhaité:

if (m.matches())
{
   String result = m.group(1);
   // do something with result
}
1
Shirik
    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++;
        }
0
Shubham Khurana