Tu vas sans doute me trouver un peu folle mais j’aime les regex 🫢

Ça a d’ailleurs souvent été un débat avec mon frère, qui est aussi développeur, et qui rechigne à les utiliser. Quand on en parle, j’ai l’étrange l’impression qu’il me voit comme une partisane du côté obscur… Développant la nuit, telle une hackeuse, me moquant des gens qui ne savent pas installer une imprimante et mettant au point un complot contre les résistants.

MAIS ! Il est tout à fait possible de les aimer sans être un(e) psychopathe. Et je ne suis pas la seule dans ce cas… Vois plutôt ce sondage réalisé auprès de la communauté des Joies Du Code, il est très parlant !

C’est quoi déjà une regex ?

Une regex est la contraction de Regular Expression. C’est à dire qu’une séquence de caractères va définir les conditions que devra respecter la constante ou variable à laquelle elle va être comparée. C’est comme si on les comparait à un modèle.

Les expressions régulières utilisent une syntaxe spécifique pour définir ces conditions.

Par exemple, le motif ^[A-Za-z]+$ correspond à une chaîne de caractères qui contient uniquement des lettres de A à Z, tant en majuscules qu’en minuscules, et qui ne contient aucun autre caractère.

Elles sont utilisées dans de nombreux langages de programmation, y compris Swift. On les utilise pour effectuer des opérations telles que la recherche de chaînes de caractères dans un texte, la validation du format des adresses mails ou d’un mot de passe.

• Comprendre le fonctionnement des regex

Voici un exemple de regex :

"^[A-Z0-9a-z._-]+@[A-Za-z.-]+.[A-Za-z]{2,3}+$"

Explications :

  • Ici, nous cherchons à faire correspondre une adresse mail qui contient un caractère présent dans la liste [A-Z0-9a-z._-] (toutes lettres majuscule ou minuscule, chiffres, ou caractère spécial . ou _ ou -). Le signe + indique « entre une fois et l’infini ». C’est à dire que que je peux retrouver ces caractères autant de fois que l’auteur voudra bien l’écrire.
  • @ correspond au caractère @
  • . correspond au point .
  • {2,3}+ signifie que ce que se trouve dans les crochets précédents peut être répété entre 2 et 3 fois
  • ^ et $ correspondent au début/à la fin de chaque ligne

Utiliser les regex avec Swift

Pour utiliser les regex dans ton projet, tu vas pouvoir utiliser soit un pattern, comme on l’a vu juste avant, soit une expression littérale. C’est à dire qu’on utilise une syntaxe différente où les lettres utilisées dans l’expression renvoient à un élément plutôt qu’à une lettre en elle-même. On l’écrit entre slashs / /.

Dans cet exemple, l’expression régulière correspond à toute chaîne de caractères qui contient une clé et une valeur séparées par deux points et un espace :

let keyAndValue = /(.+?): (.+)/

NSRegularExpression

Encore une fois avec Apple, nous pouvons utiliser cette classe pour gérer les regex en Swift sur toutes les plateformes – iOS, macOs, watchOS et même tvOS. C’est donc un moyen efficace et rapide de rechercher et de remplacer un texte complexe des dizaines et des dizaines de fois.

Voici la syntaxe pour créer une variable regex qui est construite à partir de la classe NSRegularExpression :

let email = "bonjour@objectif-appli.com"
let range = NSRange(location: 0, length: email.utf16.count)

Ici, NSRange représente la longueur de la variable string que nous allons utiliser. C’est à dire que nous voulons extraire une sous-chaîne commençant à la première position de caractère (location : 0) et ayant une longueur du nombre de caractère de notre variable str.

On utilise habituellement utf8 lorsque nous codons des applications mais ici, le fait d’utiliser utf16 permet de prévenir des erreurs de caractère, notamment avec les smileys.

Ensuite, nous allons créer une instance NSRegularExpression en reprenant la syntaxe vue plus haut:

let regex = try! NSRegularExpression(pattern: "^[A-Z0-9a-z._-]+@[A-Za-z.-]+.[A-Za-z]{2,3}+$", options: [.caseInsensitive])

On peut rajouter l’option .caseInsensitive pour que la comparaison soit insensible à la casse (c’est à dire qu’elle ne se préoccupe pas des majuscules ou minuscule). Mais cette option étant déjà gérée dans la regex, je te l’ai montrée pour l’exemple 😉

Pour tester si notre adresse mail correspond bien au pattern de la regex, nous faisons matcher les deux :

regex.firstMatch(in: email, options: [], range: range) != nil
// Renvoie true

Bien sûr, quand tu risques d’utiliser plusieurs fois la même validation avec la même regex, tu penses bien à créer une fonction dédiée, que tu pourras appeler de n’importe où dans ton code.

D’autres ressources intéressantes à lire sur NSRegularExpression :

• Utiliser la structure Regex

On peut utiliser la structure Regex pour rechercher un motif dans une chaîne de caractère, par exemple. Elle utilise NSRegularExpression pour implémenter les fonctionnalités des expressions régulières.

let str = "J'ai 4 ans, ma soeur en a 8."
let numbers = try Regex("[0-9]+")
if str.contains(numbers){
    print("Yeah baby.")
}
// Affiche "Yeah baby."

En utilisant l’expression littérale vue plus haut :

let test = "Année: 2023"
let keyAndValue = /(.+?): (.+)/
if let match = test.firstMatch(of: keyAndValue) {
    print("Key: \(match.1)")
    print("Value: \(match.2)")
}
// Key: Année
// Value: 2023

• Autres utilisation des regex

Nous avons vu que les expressions régulières étaient utilisées pour valider une chaîne de caractère. Mais elles sont aussi très utiles pour remplacer des lettres, mots ou autres éléments. On peut également les utiliser pour séparer une phrase ou encore enlever des espace.

let str = "Salut        toi    🤭       "
let strReplacing = str.replacing(/\s+/,with:",") // "Salut,toi,🤭,"
let strTrimming = str.trimmingPrefix(/\w+\s+/) // "toi    🤭       "
let fields = str.split(separator: /\s+/) // ["Salut", "toi", "🤭"]
  • replacing : Renvoie une nouvelle version de la phrase en remplaçant les espaces par une virgule
  • trimmingPrefix : Renvoie une nouvelle version de la phrase, sans le premier élément
  • split : Renvoie les éléments dans un tableau, en ne tenant pas compte des espaces

RegexBuilder

Il permet de construire des regex de manière plus structurée et plus lisible. Il transforme les regex en texte.

Tu peux transformer une expression littérale (malheureusement pas un pattern 🫤) d’une regex en faisant clic droit sur la variable > Refractor > Convert to Regex Builder. Reprenons l’exemple de tout à l’heure :

let keyAndValue = /(.+?): (.+)/

// devient

let keyAndValue = Regex {
    Capture {
        OneOrMore(.reluctant) {
            /./
        }
    }
    ": "
    Capture {
        OneOrMore {
            /./
        }
    }
}

Cool, non ?

Ressources utiles pour gérer les regex

  • Regex Crossword. Le retour du moment où tu vas me trouver folle MAIS ce site est tellement génial que j’y ai passé du temps ! C’est un site pour jouer à des mots croisés sur les regex 😃 Et je te le recommande si tu veux t’investir dans ton apprentissage de ces petites choses merveilleuses.
  • Regex101 : LE site pour comprendre une regex. Tu peux copier/coller un pattern provenant d’internet, ce site t’expliquera chaque petite partie de celui-ci. Tu pourras également tester des exemples pour voir s’ils matchent avec ton pattern.
  • Une explication plus approfondie (en français) de ce que peut être une regex.


Et voilà, j’espère que tu auras, l’espace d’un instant, partagé mon amour des regex. Sinon, j’espère que tu les détesteras moins 🫶

Quels sont tes petits « tips » pour t’en sortir avec les regex ?

Cet article est compatible avec Swift 5.8

Si tu as aimé cet article, partage le 🫶