Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Substitutions via des expressions régulières

Compilation d'expressions régulières Extraction de données par expressions régulières



Accès rapide :
La vidéo
Substitutions par le biais de la classe java.lang.String
Substitutions par le biais de la classe java.util.regex.Pattern
Gestion de la casse (minuscules/majuscules)
Réinjection de valeurs grâce aux expressions régulières
Suppression de valeurs grâce aux expressions régulières

La vidéo

Cette vidéo vous montre comment faire des remplacements (des substitutions) de chaînes de caractères à partir d'expressions régulières.


Substitutions via des expressions régulières

Substitutions par le biais de la classe java.lang.String

La classe String, permettant la manipulation de chaînes de caractères, expose quelques méthodes travaillant avec des expressions régulières. Parmi ces méthodes, citons String.replaceAll. Elle ressemble beaucoup à la méthode String.replace, à la différence que String.replace travaille avec des simples chaînes de caractères alors que String.replaceAll localise les sous-chaînes à substituer grâce à une expression régulière.

L'exemple ci-dessous remplace toutes les paires de chiffres (quels que soient les chiffres considérés) par la chaîne "xx" (un peu comme le brouillage de code d'une carte bleu sur un ticket de transaction).

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
public class Substitutions {

    public static void main(String[] args) {
        
        // --- Scrambling personal number --- 
        String myPhone = "01 02 03 04 05";
        System.out.println( myPhone.replaceAll( "\\d\\d", "xx" ) );
        //System.out.println( myPhone.replaceFirst( "\\d\\d", "xx" ) );

    }
}
Remplacement de paires de chiffres
comme nous l'avons déjà dit dans un chapitre précédent, en Java le caractère "\" pose un souci avec l'utilisation des expressions régulières. Effectivement, ce caractère a du sens dans les deux langages (Java et expressions régulières). Du coup, il est nécessaire dans une chaîne Java de doubler de caractère afin qu'il soit correctement vu dans l'expression régulière.

Deux autres méthodes similaires existent : replaceFirst qui ne remplace que la première occurrence de l'expression régulière et replaceLast qui ne remplacera que la dernière occurrence.

N'oubliez pas qu'une expression régulière doit être transformée en une machine à nombre d'états fini : nous en avons parlé dans le chapitre précédent. On parle de compilation d'expression régulière. Si vous utilisez plus d'une fois une expression régulière alors il est vivement conseillé de la compiler pour garantir des temps d'exécution optimums. Du coup, une question se pose : peut-on aussi faire des substitutions à partir de la classe Pattern ? Bien entendu, la réponse est ... oui !

Substitutions par le biais de la classe java.util.regex.Pattern

Pour rappel, on compile une expression régulière invoquant la méthode Pattern.compile. Ensuite on récupère un Matcher permettant de trouver les correspondances. Voici un exemple qui remplace toutes les ensembles de plusieurs séparateurs (blancs et tabulations) par un seul espace.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
import java.util.regex.Pattern;

public class Substitutions {

    public static void main(String[] args) {

        // --- Replace multiple separators by only one space ---
        String str = "This    is    \t       a string  with\tmultiple     \n        separators";        
        Pattern separatorsPattern = Pattern.compile( "\\s+" );
        
        System.out.println( separatorsPattern.matcher( str ).replaceAll( " " ) );
                
    }
    
}
Substitutions par le biais d'une instance de la classe Pattern
de même que sur la classe String, on retrouve une méthode replaceAll sur le matcher.

Ce programme affiche, bien entendu, la chaîne This is a string with multiple separators, sans doubles séparateurs. Le fait de remplacer chaque occurrence de (\s+) garanti qu'un tab sera aussi remplacé par un espace (même s'il est seul).

Gestion de la casse (minuscules/majuscules)

Parfois on souhaite faire des substitutions quand le motif est reconnu en minuscules, mais aussi en majuscules. Dans ce cas, ne doublez pas l'expression régulière, mais indiquez plutôt que vous souhaitez trouvez les correspondances en étant insensible à la casse. Cela se fait en rajoutant la valeur Pattern.CASE_INSENSITIVE en paramètre lors de la compilation de votre expression régulière.

Il est aussi possible de configurer la machine à états en indiquant que la chaîne de caractères sera multi-lignes et que le caractère . devra correspondre à n'importe quel caractère, y compris retour à la ligne. Pour ce faire, il faudra utiliser la valeur Pattern.DOTALL. Voici un exemple qui mixe ces deux configurations.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
import java.util.regex.Pattern;

public class Substitutions {

    public static void main(String[] args) {

        String requestParameter = "Begin\n"
                + "<Script type='text/javascript'>code</Script>\n"
                + "Middle\n"
                + "<script type='text/javascript'>\n"
                + "    window.alert( 'ok' );\n"
                + "</script>\n"
                + "End\n";

        Pattern removeCodePattern = Pattern.compile("<script[^>]*?>.*?</script>",
                                        Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
        String safeParam = removeCodePattern.matcher( requestParameter ).replaceAll( "" );
        System.out.println( safeParam );
               
    }
    
}

Et voici les résultats produit par cet exemple de code.

$> java Substitutions
Begin

Middle

End
$>

Réinjection de valeurs grâce aux expressions régulières

Il est possible de réinjecter une donnée sélectionnée par l'expression régulière, quitte à la modifier, dans la chaîne finale. Pour ce faire, il faudra utiliser une paire de parenthèses pour identifier la donnée à sélectionner dans votre expression régulière. Puis il faudra utiliser la syntaxe $1 pour réinjecter cette valeur. Il peut y avoir plusieurs occurrences sélectionnées (via plusieurs paires de parenthèses) et dans ce cas, vous pourrez aussi utiliser $2, ...

Voici un exemple de réinjection de données. La donnée d'entrée correspond à un code HTML. La donnée réinjectée, une occurrence du mot html y est mise en gras (tag <b> ... </b>).

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
import java.util.regex.Pattern;

public class Substitutions {

    public static void main(String[] args) {
        
        // --- Bold some words in an HTML stream ---
        String message = "This is an HTML content injected in a html tag";
        Pattern boldPattern = Pattern.compile( "(html)", Pattern.CASE_INSENSITIVE );
        System.out.println( boldPattern.matcher( message ).replaceAll( "<b>$1</b>" ) );
        
    }
    
}
Exemple de réinjection de valeurs

Et voici le résultat produit par cet exemple.

$> java Substitutions
This is an <b>HTML</b> content injected in a <b>html</b> tag
$>

Suppression de valeurs grâce aux expressions régulières

En fait, nous avons déjà répondu à ce besoin : en remplaçant les occurrences sélectionnées par l'expression régulière par "", on supprime les valeurs de la chaîne finale.



Compilation d'expressions régulières Extraction de données par expressions régulières