7 Expressions régulières

La Section 2.4.3.5 montre des exemples simples de recherches de chaînes de caractères. Celle-ci s’attarde à présenter un moyen de faire des recherches plus avancées, à l’aide de ce que l’on appelle les expressions régulières (ou regular expressions, abrégé par regex), qui sont des séquences de caractères formant un motif de recherche (ou search pattern).

Avant d’aller plus loin, il convient de rappeler au lecteur ou à la lectrice l’existence de l’aide sous R. La page réservée aux regex, accessible en évaluant la commande ?regex (package base), est un bon aide mémoire. Par ailleurs, le cours intitulé “Les expressions régulières” sur OpenClassrooms est un bon support6. Cependant, R possède quelques terminologiques qui lui sont propres, et qui diffèrent légèrement du cours proposé sur OpenClassrooms.

7.1 Les recherches basiques

Les fonctions qui emploient les regex en R attendent au minimum deux arguments :

  • un premier pour indiquer la chaîne de caractères (ou le vecteur de chaînes de caractères) sur lequel (lesquels) les recherches vont être effectuées ;
  • un deuxième pour préciser le motif (pattern) à rechercher. C’est l’argument qui contient l’expression régulière

Lorsque l’expression est trouvée dans une chaîne de caractère, on dit qu’il y a match (ou appariement).

Le package {base} offre de nombreuses fonctions pour effectuer des manipulations de chaînes de caractères à l’aide des expressions régulières. Elles souffrent toutefois quelques légers problèmes : il y a peu d’unité dans la syntaxe de ces fonctions et le nom de certaines d’entre-elles n’est pas immédiatement compréhensible. Aussi, nous ne nous attarderont pas à vous faire part du panorama des fonctions du package {base} ici. Nous passerons davantage de temps sur les fonctions du package {stringr}, qui s’appuient, pour la plupart d’entre-elles, sur des fonctions du package {base}.

Le nom des fonction du package {stringr} possède le préfixe _. Les deux arguments principaux indiquant le texte et le vecteur de chaînes de caractères et le motif sont appelés string et pattern. La syntaxe des fonctions de {stringr} est donc comme suit :

str_function(string, pattern)

7.1.1 Détection d’un motif avec str_detect()

Pour détecter la présence ou l’absence d’un motif dans une chaîne, on peut utiliser la fonction str_detect().

library(stringr)
textes <- c("J'ai pas le temps, j'ai matériellement pas le temps de faire ça",
           "Y a pas assez d'chaises ici ?",
           "J'ai")

str_detect(textes, "j'ai")
## [1]  TRUE FALSE FALSE
# En ignorant la casse
str_detect(string = textes,
           pattern = regex("j'ai", ignore_case = TRUE))
## [1]  TRUE FALSE  TRUE

Si on désire rechercher la présence d’un motif ou d’un autre dans un texte, on peut effectuer à la main des appels multiples à une fonction de recherche, un appel par texte à chercher, ou on peut plus simplement utiliser l’opérateur logique “Ou”, qui s’écrit | en R.

textes  <- c("J’accepte votre bonjour, Ashley.",
            "Et je vous l’échange contre un coucou.", 
            "Coucou !")
motif <- "coucou|Ashley"
str_detect(string = textes, pattern = motif)
## [1]  TRUE  TRUE FALSE

Le premier élément du vecteur textes contient le mot "Ashley" mais pas "coucou". Il y a bien au moins une des deux sous-chaînes qui a été trouvée. Le troisième élément, en revanche, ne contient ni "coucou", ni "Ashley" (il ne faut pas oublier que les fonctions traitant les expressions régulières sont par défaut sensibles à la casse en R).

Pour chercher si un motif est présent en début de texte, on fait débuter la sous-chaîne à matcher par un accent circonflexe. Pour chercher si un motif est en fin de texte, on termine la sous-chaîne à matcher par un symbole dollar.

textes <- c("Mais je ne mange pas, voyons !",
          "Mais je ne mange pas", "voyons ! Mais")
str_detect(string = textes, pattern = "^Mais")
## [1]  TRUE  TRUE FALSE
str_detect(string = textes, pattern = "je ne mange pas$")
## [1] FALSE  TRUE FALSE

7.2 Les classes de caractères

Les classes de caractères sont des listes de caractères appartenant à un ensemble, comme par exemple les caractètres alphabétiques, numériques, alphanumériques, etc. Il est possible de les construire soi-même, ou bien d’utiliser des classes prédéfinies. Elles sont écrites en les plaçant entre des crochets [classe].

Par exemple, si on désire chercher s’il y a des occurrences du caractère o ou i entre les sous-chaînes Cr et q, on définit la classe de caractères [oi] :

str_detect(string = c("Criquette", "Craquer", "Croquette"),
           pattern = "Cr[oi]q", )
## [1]  TRUE FALSE  TRUE

On a cherché dans chaque élément de string, s’il y avait la chaîne Croq ou Criq.

La construction d’une classe de caractère comme [oi] ne représente peut-être pas un attrait énorme, mais il est possible d’en créer d’autres plus alléchantes. En effet, en utilisant le tiret (-), on peut définir une séquence de caractère. Ainsi, la classe de caractères [A-Z] permet de matcher les lettres de l’ensemble ABCDEFGHIJKLMNOPQRSTUVWXYZ, tandis que [0-9] permet de matcher les caractères de l’ensemble 0123456789.

# Recherche une voyelle minuscule
str_detect(c("_!", "ALLO", "Allo 9-1-1", "9-1-1"), "[aeiou]")
## [1] FALSE FALSE  TRUE FALSE
# Recherche une voyelle majuscule
str_detect(c("_!", "ALLO", "Allo 9-1-1", "9-1-1"), "[AEIOU]")
## [1] FALSE  TRUE  TRUE FALSE
# Recherche un cacractère numérique
str_detect(c("_!", "Allo", "Allo 9-1-1", "9-1-1"), "[0-9]")
## [1] FALSE FALSE  TRUE  TRUE
# Recherche un cacractère alphabétique ASCII majuscule
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[A-Z]")
## [1] FALSE  TRUE FALSE  TRUE FALSE
# Recherche un cacractère alphabétique ASCII minuscule
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[a-z]")
## [1] FALSE  TRUE  TRUE FALSE FALSE
# Recherche un cacractère alphabétique (majuscule ou minuscule)
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[A-Za-z]")
## [1] FALSE  TRUE  TRUE  TRUE FALSE
# Recherche un cacractère alphanumérique
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[A-Za-z0-9]")
## [1] FALSE  TRUE  TRUE  TRUE  TRUE

Si l’utilisateur•trice désire rechercher un caractère qui n’appartient pas à une classe de caractères, il suffit de rajouter un accent circonflèxe (^) juste après le crochet ouvrant. Si on désire rechercher la présence de l’accent circonflèxe dans un texte, en utilisant une classe de caractère, il faut placer le symbole autre part que juste après le crochet. Pour chercher un crochet fermant (ouvrant) il faut le faire précéder des doubles barres obliques inverses. Enfin, pour chercher un tiret, il suffit de la placer en premier ou en dernier de la définition de la classe.

# Y a-t-t-il autre chose que des chiffres ?
str_detect(c("_!", "Allo", "Allo 9-1-1", "911"), "[^0-9]")
## [1]  TRUE  TRUE  TRUE FALSE
# Recherche de l'accent circonflèxe ou d'un chiffre
str_detect(c("_!", "Allo", "Allo ^ accent", "Allo 9-1-1", "911"), "[0-9^]")
## [1] FALSE FALSE  TRUE  TRUE  TRUE
# Rechercher un crochet
str_detect(c("_!", "All[o", "All]o ^ accent", "Allo 9-1-1", "911"), "[\\[\\]]")
## [1] FALSE  TRUE  TRUE FALSE FALSE
# Rechercher un tiret ou un i
str_detect(c("_!", "All[o", "All-] ^ accent", "Allo 9-1-1", "9i11"), "[-i]")
## [1] FALSE FALSE  TRUE  TRUE  TRUE

Il ne faut pas confondre l’accent circonflèxe inséré entre les crochets et celui placé au début d’une chaîne pour indiquer que le motif doit commencer par cette chaîne.

# Le texte commence-t-il par autre chose qu'un chiffre ?
str_detect(c("_!", "Allo", "9-1-1", "911"), "^[^0-9]")
## [1]  TRUE  TRUE FALSE FALSE

R propose la bibliothèque de classes appelée POSIX. Ces classes s’utilisent en faisant appel à leur nom, de la même manière que les classes définies par l’utilisateur•trice, ou les séquences : [classe]. Il faut toutefois noter que les noms des classes de caractères POSIX sont légèrement différentes en R que dans d’autres langages, comme PHP par exemple. En effet, il faut les entourer de crochets et de deux-points. Ainsi, la classe des alphanumériques sera accessible par son nom [:alnum:] et utilisée de la sorte : [[:alnum:]]. Le fichier d’aide des regex de R met en garde l’utilisateur•trice que ces classes de caractères prédéfinies peuvent varier selon les configurations des machines, notamment les configurations linguisitiques. Voici quelques exemples.

# Recherche un cacractère numérique
str_detect(c("_!", "Allo", "Allo 9-1-1", "9-1-1"), "[[:digit:]]")
## [1] FALSE FALSE  TRUE  TRUE
# Rechercher un caractère non-numérique
str_detect(c("_!", "Allo", "Allo 9-1-1", "911"), "[^[:digit:]]")
## [1]  TRUE  TRUE  TRUE FALSE
# Recherche un cacractère alphabétique majuscule
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[[:upper:]]")
## [1] FALSE  TRUE FALSE  TRUE FALSE
# Recherche un cacractère alphabétique minuscule
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[[:lower:]]")
## [1] FALSE  TRUE  TRUE FALSE FALSE
# Recherche un cacractère alphabétique (majuscule ou minuscule)
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[[:alpha:]]")
## [1] FALSE  TRUE  TRUE  TRUE FALSE
# Recherche un cacractère alphanumérique
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "[[:alnum:]]")
## [1] FALSE  TRUE  TRUE  TRUE  TRUE
# Recherche une espace ou une tabulation
str_detect(c("_!", "Allo\t", "Allo 9-1-1"), "[[:blank:]]")
## [1] FALSE  TRUE  TRUE
# Recherche d'un caractère de ponctuation
# (! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~)
str_detect(c("_!", "Allo", "Allo 9-1-1", "9-1-1"), "[[:punct:]]")
## [1]  TRUE FALSE  TRUE  TRUE

R propose également quelques abréviations pour accéder à certaines classes. On y accède en écrivant une lettre minuscule précédée de deux barre obliques inversées. Si la lettre est en majuscule, il s’agit de la recherche de non appartenance à la classe. Par exemple, \\d recherche un caractère numérique (digital), et \\D recherche un caractère n’étant pas numérique. Voici quelques exemples.

# Recherche un cacractère numérique
str_detect(c("_!", "Allo", "Allo 9-1-1", "911"), "\\d")
## [1] FALSE FALSE  TRUE  TRUE
# Recherche un caractère non-numérique
str_detect(c("_!", "Allo", "Allo 9-1-1", "911"), "\\D")
## [1]  TRUE  TRUE  TRUE FALSE
# Recherche un cacractère alphanumérique
# Attention à cette abréviation qui match le trait de soulignement...
str_detect(c("_!", "Allo", "allo", "ALLO", "9-1-1"), "\\w")
## [1] TRUE TRUE TRUE TRUE TRUE

Le tableau ci-dessous donne un récapitulatif des classes de caractères prédéfinies.

ASCII POSIX Raccourcis Description
[[:lower:]] [a-z] Lettre minuscule
[[:upper:]] [A-Z] Lettre majuscule
[[:alpha:]] [a-zA-Z] Lettre minuscule et majuscule
[[:digit:]] [0-9] \\d Chiffres de 0 à 9
[[:alnum:]] [a-zA-Z0-9] Caractère alphanumérique
[[:blank:]] [\t] Espace et tabulation
[[:cntrl:]] Caractère de contrôle
[[:punct:]] []!\"#$\\%&\'\\(\\)*+,-\\./:;<=>\\?@^_`{|}~[] Ponctuation et symbole
[[:space:]] [ \t\r\n\v\f] \\s Espace blanc ou séparateur de ligne ou de paragraphe
[[:xdigit:]] [A-Fa-f0-9] Chiffre hexadécimal
[[:print:]] [A-Fa-f0-9] Caractère visible et espace (tout sauf caractère de contrôle)
[[:graph:]] [\x20-\x7E] Caractère graphique visible (tout sauf espace et caractère de contrôle)
[A-Za-z0-9_] \\w Lettre, chiffre et trait de soulignement

7.3 Les quantificateurs

Afin de pouvoir chercher des motifs qui se répètent, dans un nombre défini a priori ou non, on peut utiliser ce que l’on appelle des quantificateurs.

Les principaux quantificateurs sont les suivants :

  • ? : le précédent item est factultatif, et sera donc matché \(0\) ou \(1\) fois ;
  • * : le précédent item sera matché \(0\) fois ou plus ;
  • + : le précédent item sera matché \(1\) fois ou plus ;
  • n : le précédent item sera matché exactement n fois ;
  • n, : le précédent item sera matché \(n\) fois ou plus ;
  • n,m : le précédent item sera matché au mois \(n\) fois, mais pas plus de \(m\) fois.

Quelques exemple pour se fixer les idées.

# La chaîne "travaille " peut être présente 0 ou 1 fois
textes <- c("Lolo travaille au skateshop", "Lolo au skateshop")
str_detect(textes, "Lolo (travaille )?au skateshop")
## [1] TRUE TRUE
# Cherche "ah Sonia", ou "ahah Sonia", ou "ahahah Sonia", etc.
textes <- c("ahahah Sonia", "ahah Sonia", "Sonia", "Amandine")
str_detect(textes, "(ah)* Sonia")
## [1]  TRUE  TRUE FALSE FALSE
# On souhaite s'assurer qu'il y a au moins un "ah" suivi de " Stéphanie"
# Mais on peut aussi avoir "ahah Stéphanie" ou "ahahah Stéphanie"
textes <- c("Bonjour Stéphanie", "ah Stéphanie", "ahah Stéphanie")
str_detect(textes, "(ah)+")
## [1] FALSE  TRUE  TRUE
textes <- c("a#maisoui#maisoui !", "a#maisoui !", "a#maisoui#maisoui#maisoui !",
           "a#maisoui#maisoui#maisoui#maisoui !")

# Y a-t-il une sous chaîne "a#maisoui#maisoui !" dans le texte ?
str_detect(textes, "a(#maisoui){2} !")
## [1]  TRUE FALSE FALSE FALSE
# Y a-t-il une sous chaîne "a#maisoui#maisoui !", ou
# "a#maisoui#maisoui#maisoui !", etc. dans le texte ?
str_detect(textes, "a(#maisoui){2,} !")
## [1]  TRUE FALSE  TRUE  TRUE
# La chaîne "skate" sera présente entre deux et trois fois
str_detect(textes, "a(#maisoui){2,3} !")
## [1]  TRUE FALSE  TRUE FALSE

7.4 Les métacaractères

Les regex possèdent quelques caractères spéciaux, qui ont un statut réservé, et qui sont appelés des métacaractères. L’accent circonflèxe en fait partie. En effet, l’expression régulière ^Bonjour ne recherchera pas la chaîne "^Bonjour", comme vu plus haut.

La liste des métacaractères est la suivante : . \| ( ) [ { $ * + ?

En R pour pouvoir rechercher ces caractères dans des chaînes, il faut les échapper, à l’aide de deux barres obliques inversées \\.

textes <- c("Clément et Marianne vont chez Thibault.",
           "Clément (et Marianne) vont chez Thibault !")

# Recherche la présence de "et Marianne"
str_detect(textes, "(et Marianne)")
## [1] TRUE TRUE
# Recherche la présence de "(et Marianne)"
str_detect(textes, "\\(et Marianne\\)")
## [1] FALSE  TRUE
# Le dernier caractère est-il n'importe quel caractère ?
str_detect(textes, ".$")
## [1] TRUE TRUE
# Le texte se termine-t-il par un point ?
str_detect(textes, "\\.$")
## [1]  TRUE FALSE

7.5 Quelques fonctions du package {stringr}

Regardons à présent quelques fonctions de {stringr} qui permettent de manipuler des chaînes de caractères à l’aide d’expressions régulières.

7.5.1 La fonction str_detect()

Pour extraire une chaîne qui contient un motif, on peut utiliser la fonction str_extract(). Le résultat est un vecteur de caractères de la même longueur que celui fourni à l’argument string. Pour les éméments pour lesquels il n’y a pas eu de match, la valeur NA est retournée.

adresses <- c("criquette.rockwell@gmail.com",
              "brett.montgomery@yahoo.fr",
              "madge_laposte.net")
motif <- "^[[:alnum:].-]+@[[:alnum:].-]+$"

# Extraire les adresses e-mail valides
str_extract(string = adresses, pattern = motif)
## [1] "criquette.rockwell@gmail.com" "brett.montgomery@yahoo.fr"   
## [3] NA

7.5.2 La fonction str_extract_all()

Alors que la fonction str_extract() ne permet d’extraire que la première chaîne qui match le motif, str_extract_all() retourne toutes les occurrences trouvées. Le résultat est une liste de la même longueur que celle du vecteur fourni à l’argument string. Les éléments de cette liste sont des vecteurs de la taille du nombre d’occurrences du motif trouvé. En cas d’absence de match, la valeur character(0) est retournée.

tweets <- c("@kevin_ushey yes sure, it was just an example",
            "@hspter @kwbroman next is to get into #github streak art.")
motif <- c("@[[:alpha:]]{1,}")

# Extraire la première mention trouvée
str_extract(tweets, motif)
## [1] "@kevin"  "@hspter"
# Extraire toutes les mentions trouvées
str_extract_all(tweets, motif)
## [[1]]
## [1] "@kevin"
## 
## [[2]]
## [1] "@hspter"   "@kwbroman"

7.5.3 La fonction str_match()

La fonction str_match() extrait le premier groupe trouvé dans une chaîne. Il est donc nécessaire que l’argument pattern contienne un ou des groupes (définis par les parenthèses ()). Le résultat est une matrice dont la première colonne contient le match complet, les suivantes sont les matches pour chaque groupe.

telephones <- c("02 23 23 35 45", "02-23-23-35-45", "Madrid",
                "02.23.23.35.45", "0223233545", "Milan",
                "02 23 23 35 45  ", " 02 23 23 35 45",
                "Maison : 02 23 23 35 45")

motif_tel <- str_c(str_dup("([0-9]{2})[- \\.]", 4),  "([0-9]{2})")

# Extrait les numéros de téléphone
str_extract(telephones, motif_tel)
## [1] "02 23 23 35 45" "02-23-23-35-45" NA               "02.23.23.35.45"
## [5] NA               NA               "02 23 23 35 45" "02 23 23 35 45"
## [9] "02 23 23 35 45"
str_match(telephones, motif_tel)
##       [,1]             [,2] [,3] [,4] [,5] [,6]
##  [1,] "02 23 23 35 45" "02" "23" "23" "35" "45"
##  [2,] "02-23-23-35-45" "02" "23" "23" "35" "45"
##  [3,] NA               NA   NA   NA   NA   NA  
##  [4,] "02.23.23.35.45" "02" "23" "23" "35" "45"
##  [5,] NA               NA   NA   NA   NA   NA  
##  [6,] NA               NA   NA   NA   NA   NA  
##  [7,] "02 23 23 35 45" "02" "23" "23" "35" "45"
##  [8,] "02 23 23 35 45" "02" "23" "23" "35" "45"
##  [9,] "02 23 23 35 45" "02" "23" "23" "35" "45"

7.5.4 La fonction str_match_all()

Si la chaîne de caractère contient plusieurs matches, la fonction str_match() ne retournera que le premier. Pour les avoir tous, il faut utiliser la fonction str_match_all(). Le résultat est une liste de la même longueur que le vecteur fourni à string. Chaque élément de la liste, lorsqu’il y a eu match est une matrice comme celle retournée par str_match(). S’il n’y a pas eu match, l’élément de la liste retournée est character(0).

telephones <- c("02 23 23 35 45", "02-23-23-35-45 / 02 23 23 35 35",
                "Madrid", "Maison : 02.23.23.35.45, Travail : 02 23 23 35 35")


motif_tel <- str_c(str_dup("([0-9]{2})[- \\.]", 4),  "([0-9]{2})")

# Extrait les numéros de téléphone
str_extract_all(telephones, motif_tel)
## [[1]]
## [1] "02 23 23 35 45"
## 
## [[2]]
## [1] "02-23-23-35-45" "02 23 23 35 35"
## 
## [[3]]
## character(0)
## 
## [[4]]
## [1] "02.23.23.35.45" "02 23 23 35 35"
str_match_all(telephones, motif_tel)[[3]]
##      [,1] [,2] [,3] [,4] [,5] [,6]

7.5.5 La fonction str_locate()

Pour localiser la position de la première occurrence d’un motif dans une chaîne, on peut utiliser la fonction str_locate(). Le résultat est une matrice d’entiers dont la première colonne indique la position de départ du match et la seconde indique la position de fin du match. En cas d’absence de match, les deux valeurs valent NA.

fruits <- c("pomme", "banane", "poire", "ananas")
str_locate(fruits, "a")
##      start end
## [1,]    NA  NA
## [2,]     2   2
## [3,]    NA  NA
## [4,]     1   1
# On peut définir le motif pour chaque élément du texte
str_locate(fruits, c("p", "o", "p", "a"))
##      start end
## [1,]     1   1
## [2,]    NA  NA
## [3,]     1   1
## [4,]     1   1

7.5.6 La fonction str_locate_all()

Si on désire obtenir la position de toutes les occurrences d’un motif dans une chaîne, on peut utiliser la fonction str_locate_all(). Le résultat est une liste de la même longueur que le vecteur fourni à l’argument string. Chaque élément de la liste contient une matrice d’entiers dont la première colonne contient les positions de départ des matches et la seconde les positions de fin. Chaque ligne de la matrice correspond à un match. En cas d’absence de match dans la chaîne, la matrice retournée est matrix(0, nrow = 0, ncol = 2).

fruits <- c("pomme", "banane", "poire", "ananas")
str_locate_all(fruits, "a")
## [[1]]
##      start end
## 
## [[2]]
##      start end
## [1,]     2   2
## [2,]     4   4
## 
## [[3]]
##      start end
## 
## [[4]]
##      start end
## [1,]     1   1
## [2,]     3   3
## [3,]     5   5
# On peut définir le motif pour chaque élément du texte
str_locate_all(fruits, c("p", "o", "p", "a"))
## [[1]]
##      start end
## [1,]     1   1
## 
## [[2]]
##      start end
## 
## [[3]]
##      start end
## [1,]     1   1
## 
## [[4]]
##      start end
## [1,]     1   1
## [2,]     3   3
## [3,]     5   5

7.5.7 La fonction str_replace()

La fonction str_replace() remplace la première occurrence d’un motif matché par la chaîne indiquée à l’argument replacement.

telephones <- c("02/23/23/35/45", "02.23.23.35.45", "02 23 23 35 45")

# Remplacer la première occurrence du motif trouvée par un tiret
str_replace(telephones, "[/ \\.]", "-")
## [1] "02-23/23/35/45" "02-23.23.35.45" "02-23 23 35 45"

Lorsqu’il y a des groupes (définis par des parenthèses), on peut faire référence aux groupes matchés à l’aide de deux barres obliques inversées suivies du rang du groupe. Ainsi \\1 fera référence au premier groupe matché.

fruits <- c("01. pomme", "02. pêches", "Maison", "03. bananes")
str_replace(fruits, "([0-9]{2}\\. )([a-z])", "Debut\\1Bonjour\\2Fin")
## [1] "Debut01. BonjourpFinomme"   "Debut02. BonjourpFinêches" 
## [3] "Maison"                     "Debut03. BonjourbFinananes"

7.5.8 La fonction str_replace_all()

La fonction str_replace_all() permet de remplacer toutes les occurrences du motif trouvé par une chaîne de remplacement.

telephones <- c("02/23/23/35/45", "02.23.23.35.45", "02 23 23 35 45")

# Remplacer toute les occurrences du motif trouvées par un tiret
str_replace_all(telephones, "[/ \\.]", "-")
## [1] "02-23-23-35-45" "02-23-23-35-45" "02-23-23-35-45"

7.5.9 La fonction str_split()

La fonction str_split() permet de séparer une chaîne de caractères en plusieurs morceaux, suivant un motif donné. On peut préciser le nombre maximum de morceaux à retourner à l’aide de l’argument n. Cet argument vaut Inf par défaut, et retourne donc tous les morceaux qu"il est possible de trouver. Si la valeur donnée à n est plus petite que lon nombre de morceaux qu’il est possible de faire, le dernier élément du vecteur de caractères retourné contient encore des occurrences du motif. Si par contre la valeur fournie à n est plus grande, il n’y a pas de rajouts effectués par R.

Le résultat est une liste de la même longueur que le vecteur passé à l’argument string. Chaque élément de la liste contient les morceaux. Si l’argument pattern vaut NA, le résultat est le texte original, si pattern vaut "", le texte original est séparé par caractères.

textes <- c("manger des chips", "José",
            "Considère qu'on n'est plus amis, Abitbol !")

str_split(textes, " ")
## [[1]]
## [1] "manger" "des"    "chips" 
## 
## [[2]]
## [1] "José"
## 
## [[3]]
## [1] "Considère" "qu'on"     "n'est"     "plus"      "amis,"     "Abitbol"  
## [7] "!"
# Avec n plus grand
str_split(textes, " ", n = 4)
## [[1]]
## [1] "manger" "des"    "chips" 
## 
## [[2]]
## [1] "José"
## 
## [[3]]
## [1] "Considère"            "qu'on"                "n'est"               
## [4] "plus amis, Abitbol !"

7.5.10 La fonction str_string_fixed()

Pour briser une chaîne de caractères en un nombre n de morceaux fixe en fonction d’un motif pattern, on peut utiliser la fonction str_string_fixed(). Le résultat est une matrice à n, colonnes. Chaque colonne de la matrice retournée correspond à un morceau. Si n est supérieur au nombre de morceaux qu’il est possible de créer, les colonnes de la matrice retournée sont complétées par la chaine vide "". En revanche, si n est inférieur au nombre de morceaux que l’on peut créer, la dernière colonne contiendra le reste de la chaîne n’ayant pas encore été découpée.

textes <- c("manger des chips", "José",
            "Considère qu'on n'est plus amis, Abitbol !")

# Avec 4 morceaux
str_split_fixed(textes, " ", n = 4)
##      [,1]        [,2]    [,3]    [,4]                  
## [1,] "manger"    "des"   "chips" ""                    
## [2,] "José"      ""      ""      ""                    
## [3,] "Considère" "qu'on" "n'est" "plus amis, Abitbol !"

7.6 Quelques fonctions du package {base}

À titre informatif, le tableau ci-dessous présente les fonctions du package {base} les plus importantes lorsque l’on manipule des expressions régulières. Les deux arguments principaux de texte et de motif sont nommés text et pattern, respectivement. Lorsqu’elle existe, la fonction équivalente dans {stringr} est donnée.

Fonction dans {string} Fonction dans {base} Description
str_which() grep() Retourne les indices des éléments du vecteur de texte pour lequel il y a un match
str_detect() grepl() Retourne un vecteur de valeurs logiques de la même longueur que le vecteur text, qui indique, pour chaque élément, s’il y a eu match
Proche de str_locate() regexpr() Retourne un vecteur d’entiers de la même taille que text donnant la position du premier match (ou -1 s’il n’y a pas eu de match), avec l’attribut match.length, un vecteur d’entiers donnant la longueur du text match (ou -1 si pas de match).
Proche de str_locate_all gregexpr() Même chose que regexpr(), mais le résultat est sous forme de liste, dont chaque élément correspond à la recherche du motif dans l’élément de text correspondant. Par ailleurs, les positions de départ de chaque match sont données, et non pas seulement le premier rencontré. Il en est de même pour l’attribut match.length.
regexec() Retourne une liste de la même taille que text dont chaque élément est soit -1 s’il n’y a pas eu de match, ou une séquence d’entiers avec les positions de début de match de toutes les sous-chaînes correspondant aux sous-expressions parenthésées de l’argument pattern, avec l’attribut match.length, qui est un vecteur donnant la longueu de chaque match, ou -1 s’il n’y en a pas eu.

Pour se fixer les idées, voici quelques exemples. La fonction str_which(), qui permet d’indiquer les positions des éléments du vecteur donné en argument à string dans lesquels le motif est repéré :

textes <- c("Je m’évanouis avant d’avoir pu vous révéler",
          "le nom du kidnappeur", "et/ou de la kidnappeuse",
          "du petit Doug Doug !")
motif <- "ou"

str_which(string = textes, pattern = motif)
## [1] 1 3 4

La fonction str_detect() qui retourne un vecteur de logique indiquant pour chaque élément du vecteur donné en argument à string si le motif a été trouvé :

str_detect(string = textes, pattern = motif)
## [1]  TRUE FALSE  TRUE  TRUE

La fonction regexpr() (dans {base}, donne un résultat relativement proche de celui de str_locate() de {stringr}) :

regexpr(pattern = textes, text = motif)
## [1] -1
## attr(,"match.length")
## [1] -1
str_locate(string = textes, pattern = motif)
##      start end
## [1,]    10  11
## [2,]    NA  NA
## [3,]     4   5
## [4,]    11  12

La fonction gregexpr()

gregexpr(pattern = motif, text = textes)
## [[1]]
## [1] 10 33
## attr(,"match.length")
## [1] 2 2
## 
## [[2]]
## [1] -1
## attr(,"match.length")
## [1] -1
## 
## [[3]]
## [1] 4
## attr(,"match.length")
## [1] 2
## 
## [[4]]
## [1] 11 16
## attr(,"match.length")
## [1] 2 2
str_locate_all(string = textes, pattern = motif)
## [[1]]
##      start end
## [1,]    10  11
## [2,]    33  34
## 
## [[2]]
##      start end
## 
## [[3]]
##      start end
## [1,]     4   5
## 
## [[4]]
##      start end
## [1,]    11  12
## [2,]    16  17

Et enfin, la fonction regexec()

regexec(pattern = motif, text = textes)
## [[1]]
## [1] 10
## attr(,"match.length")
## [1] 2
## attr(,"useBytes")
## [1] TRUE
## 
## [[2]]
## [1] -1
## attr(,"match.length")
## [1] -1
## attr(,"useBytes")
## [1] TRUE
## 
## [[3]]
## [1] 4
## attr(,"match.length")
## [1] 2
## attr(,"useBytes")
## [1] TRUE
## 
## [[4]]
## [1] 11
## attr(,"match.length")
## [1] 2
## attr(,"useBytes")
## [1] TRUE