Éxpressions régulières
Nous allons maintenant construire un programme plus intéressant. Cette fois, nous testerons si une chaîne de caractères correspond à une certaine description, qu’on appelle une forme (pattern).
Certains caractères et combinaisons de caractères ont une signification spéciale dans les formes, notamment :
| [ ] | spécification d’intervalle (par ex: [a-z] indique une lettre dans l’intervalle a à z) |
| \w | lettre ou chiffre; équivaut à [0-9A-Za-z] |
| \W | ni lettre ni chiffre |
| \s | caractère espace ; équivaut à[ \t\n\r\f] |
| \S | caractère non espace |
| \d | chiffre; équivaut à [0-9] |
| \D | non-chiffre |
| \b | backspace (0×08) (seulement dans un intervalle) |
| \b | limite de mot (sauf dans un intervalle) |
| \B | limite autre que de mot |
| * | zero, 1 ou n occurrences de ce qui précède |
| + | 1 ou n occurrences de ce qui précède |
| {m,n} | au moins m et au plus n occurrences de ce qui précède |
| ? | Au plus une occurrence de ce qui précède; équivaut à {0,1} |
| | | alternative : soit ce qui précède soit ce qui suit |
| () | groupe |
Le nom générique pour les formes qui utilisent ce vocabulaire bizarre est expressions rationelles ou régulières, la 2e forme étant un anglicisme venant de regular expression. En ruby, comme en Perl, elles sont généralement entourées par des slashs (/) plutôt que par des guillemets. Si vous n’avez jamais utilisé les expressions régulières auparavant, elles vous paraîtront sûrement tout sauf régulières (Ndt : jeu de mot sur regular : ordinaire), mais vous avez tout intérêt à passer quelques temps à les apprivoiser. Elles ont un pouvoir d’expression concise qui vous évitera des maux de têtes et beaucoup de lignes de code, que vous ayez à faire de la reconnaissance de forme sur chaînes de caractères, des recherches de chaînes, et toutes autres manipulations de chaînes.
Par exemple, supposons que nous voulions tester si une chaîne correspond à la description suivante : « Commence par un f minuscule, suivi immédiatement par exactement une majuscule, suivie par n’importe quoi sauf des minuscules. » Si vous êtes un programmeur C expérimenté, vous avez sûrement déjà écrit mentalement une douzaine de lignes, pas vrai ? Reconnaissez-le, vous n’avez pas pu vous en empêcher. Mais en ruby vous n’avez qu’à tester votre chaîne contre l’expression régulière suivante : /^f[A-Z][^a-z]*$/.
Et si c’était « Contient un nombre hexadecimal entouré par des crochets » ? Pas de problème.
ruby> def chab (s) # "contient un hexa entre crochets"
| (s =~ /<0Xx+>/) != nil
| end
nil
ruby> chab "Pas ça."
false
ruby> chab "Peut-être ça ? {0x35}" # parenthèses, pas crochets
false
ruby> chab "Ou ça? <0x38z7e>" # hexa incorrect
false
ruby> chab "Celui-ci, oui: <0xfc0004>."
true
Quoique les expressions régulières soient déroutantes au début, vous tirerez vite des satisfactions de pouvoir vous exprimer avec une telle concision.
Voici un petit programme pour vous aider à pratiquer avec les expressions régulières. Sauvez-le en regx.rb et lancez-le en tapant ruby regx.rb.
# Requiert un terminal ANSI !
st = "033[7m"
en = "033[m"
while TRUE
print "str> "
STDOUT.flush
str = gets
break if not str
str.chop!
print "pat> "
STDOUT.flush
re = gets
break if not re
re.chop!
str.gsub! re, "#{st}\&#{en}"
print str, "n"
end
print "n"
Ce programme demande deux entrées, une pour une chaîne de caractères, et une pour l’expression régulière. La chaîne est confrontée à l’expression, puis affichée avec les parties qui répondent à l’expression en vidéo inverse. Ne vous occupez pas des détails du programme maintenant, nous l’analyserons bientôt.
str> foobar pat> ^fo+ foobar ~~~
Le « ~~ » est indique la partie de texte reconnue par l’expression régulière, colorée en rouge dans le terminal.
Essayons d’autres saisies.
str> abc012dbcd555 pat> \d abc012dbcd555 ~~~ ~~~
Si ceci vous étonne, regardez à nouveau le tableau ci-dessus : \d n’a rien à voir avec le caractère d, mais correspond à un chiffre quelconque (d pour digital).
Et s’il y a plusieurs façons de correspondre à la forme indiquée ?
str> foozboozer pat> f.*z foozboozer ~~~~~~~~
foozbooz est retenu au lieu de seulement fooz, parce qu’une expression régulière renvoie la sous-chaîne la plus longue possible.
Voici une forme pour isoler une heure avec des : comme séparateurs.
str> Wed Feb 7 08:58:04 JST 1996
pat> [0-9]+:[0-9]+(:[0-9]+)?
Wed Feb 7 08:58:04 JST 1996
~~~~~~~~
« = » est un opérateur de correspondance qui s’applique aux expressions régulières. Il retourne la position du début de la correspondance dans la chaîne, ou nil si la forme n’a pas été trouvée.
ruby> "abcdef" =~ /d/ 3 ruby> "aaaaaa" =~ /d/ nil
Précédent : GDU : Chaînes de caractères Suivant : GDU : Tableaux


