445 votes

Comment extraire une sous-chaîne à l'aide d'une expression rationnelle ?

J'ai une chaîne qui contient deux guillemets simples, le ' caractère. Entre les guillemets simples se trouvent les données que je veux.

Comment puis-je écrire une regex pour extraire "les données que je veux" du texte suivant ?

mydata = "some string with 'the data i want' inside";

657voto

Mark Byers Points 318575

En supposant que vous voulez la partie entre guillemets simples, utilisez cette expression régulière avec un Matcher :

"'(.*?)'"

Ejemplo:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

Résultat :

the data i want

12 votes

Bon sang j'oublie toujours le modificateur non gourmand :(

40 votes

Remplacez le "si" par un "pendant" lorsque vous prévoyez plusieurs occurrences.

19 votes

Gardez à l'esprit que matcher.find() est nécessaire pour que cet exemple de code fonctionne. Si vous n'appelez pas cette méthode, vous obtiendrez une exception "No match found" lorsque matcher.group(1) sera appelé.

77voto

Lucass Points 432

Vous n'avez pas besoin de regex pour cela.

Ajoutez apache commons lang à votre projet ( http://commons.apache.org/proper/commons-lang/ ), puis utilisez :

String dataYouWant = StringUtils.substringBetween(mydata, "'");

13 votes

Vous devez tenir compte de la manière dont votre logiciel sera distribué. S'il s'agit de quelque chose comme un webstart, il n'est pas judicieux d'ajouter Apache commons uniquement pour utiliser cette seule fonctionnalité. Mais peut-être que ce n'est pas le cas. De plus, Apache Commons a beaucoup plus à offrir. Même s'il est bon de connaître les expressions rationnelles, il faut être prudent quant à leur utilisation. Les expressions rationnelles peuvent être très difficiles à lire, à écrire et à déboguer. Dans un certain contexte, l'utilisation de cette méthode pourrait être la meilleure solution.

4 votes

Parfois StringUtils est déjà là, dans ces cas cette solution est beaucoup plus propre et lisible.

8 votes

C'est comme si vous achetiez une voiture pour parcourir 5 miles (lorsque vous ne voyagez qu'une fois par an).

17voto

Sean McEligot Points 36
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}

3 votes

System.out.println(matcher.group(0)) ; <--- Index basé sur le zéro

4 votes

Non. group(0) a une signification spéciale, les groupes de capture commencent à l'index group(1) (c'est-à-dire que group(1) est correct dans la réponse). "Les groupes de capture sont indexés de gauche à droite, en commençant par un. Le groupe zéro désigne le motif entier" - Source : docs.oracle.com/javase/8/docs/api/java/util/regex/

0 votes

N'oubliez pas que matches() essaie de faire correspondre la chaîne entière, donc si vous n'avez pas ".*" au début et à la fin de votre motif, il ne trouvera rien.

10voto

Debilski Points 28586

Parce que vous avez également coché Scala, une solution sans regex qui traite facilement les chaînes entre guillemets multiples :

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)

4 votes

Une solution très lisible, c'est pourquoi les gens aiment Scala je crois :)

3 votes

Pourquoi ne pas simplement .split('\'').get(2) ou quelque chose de ce genre en Java ? Je pense que vous devriez passer un scanner cérébral si vous pensez que c'est une solution lisible - il me semble que quelqu'un a essayé de faire du golf en code.

4voto

Comme dans javascript :

mydata.match(/'([^']+)'/)[1]

le regexp réel est : /'([^']+)'/

si vous utilisez le modificateur non gourmand (comme dans un autre post), c'est comme ça :

mydata.match(/'(.*?)'/)[1]

il est plus propre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X