====== Les expressions régulières ====== C'est la vie… ===== Qu'est-ce qu'une expression régulière ? ===== Tout d'abord, quelques exemples pour appréhender les notions utilisées dans cette page. Intéressons-nous par exemple à toutes les ''chaînes de caractères'' contenant « **aaa** » dans leur rédaction. \\ (//une chaîne de caractère, ce sont des caractères accolés formant par exemple un mot, une phrase ou un nom de fichier//) Une autre manière de les décrire est de parler des chaînes formées de : - //un nombre quelconque (éventuellement nul) de lettres quelconques// - suivi de « aaa » - suivi d'//un nombre quelconque (éventuellement nul) de lettres quelconques//. On appelle cette description un ''motif'', et ont dit que nos mots sont ''reconnus'' par le motif. Pour décrire les motifs à un programme, on utilise des expressions régulières (regular expression ou //regexp// en anglais). Différents programmes utilisent différentes syntaxes pour ces expressions. Dans ce tuto, nous allons principalement nous intéresser aux ''regexp'' utilisées par **sed**, **find**, **grep**, **locate** qui sont sensiblement les mêmes. ===== Construire une expression régulière ===== //C'est quand on s'exprimait quotidiennement qu'on a consommé nos ex-pressions régulières// Les expressions régulières sont elles-mêmes des chaînes de caractères. On va cependant donner à certains de ces caractères un sens tout particulier. Ces caractères sont les suivants : le point ''.'', l'étoile ''*'', les crochets ouvrant et fermant ''['' et '']'', l'accent circonflexe ''^'', le dollar ''$'' et le backslash ''\''. Dans la suite, on les appelera caractères spéciaux. ==== Les caractères ==== //Quand je vous disais que tout est une question de pied…// La première chose que l'on veut pouvoir reconnaître avec des motif, ce sont les mots que l'on peut écrire sans regexp. Exemple : « Abracadabrantesque ». Ça tombe bien, toutes les lettres sont des caractères pouvant former une regexp, et « Abracadabrantesque » est donc une regexp reconnaissant exactement le mot « Abracadabrantesque ». ==== Les jokers ==== //Ou l'appel à un ami ?// Avis aux amateurs de mots fléchés, la réponse à vos soucis est là ! Mettons nous en situation. Vous êtes à la plage sur le sable brûlant, à la montagne devant un bol de lait chaud ou plus simplement sur votre trône, et vous avez face à vous une grille de mots fléchés déjà entamée… Quels sont les mots qui peuvent rentrer dans cette case là, en dessous de la tâce ? (tâche de crème solaire, de confiture ou de… ?) ''A.racadabrant....e'' Comme vous l'aurez compris, les ''.'' signifient //n'importe quel caractère//. Figurez-vous que la chaîne ci-dessus est une regexp qui reconnaît exactement les mots entrant dans votre case problématique. En effet, ''.'' est un caractère spécial reconnaissant //n'importe quel caractère//. On appelle aussi ce caractère ''joker''((En bash, le caractère joker est ''?'')) ==== Les caractères échappés === //Attrappez-les tous !// Le disciple : - Oui mais, et si je veux reconnaître un « . » ? \\ Le maître : - Alors tu utiliseras la regexp ''\.'' ! \\ Le disciple : - Oui mais, et si je veux reconnaître un « \. » ? \\ Le maître : - Alors tu utiliseras la regexp ''\\\.'' ! \\ Le disciple : - Oui mais, et si je veux reconnaître un « \\\. » ? \\ Le maître : - Alors tu utiliseras la regexp ''\\\\\\\.'' ! \\ Le disciple : - Oui mais… \\ Le mâitre, //sortant son tromblon// : - Oui ? \\ Le disciple : - Ah… Tous nos caractères spéciaux ont des significations particulières, nous l'avons vu avec le ''.'', c'est vrai pour les autres. Ainsi, pour reconnaître chacun d'eux, il faut l'//échapper// par un ''\''. Ainsi, ''\.'' reconnaît « . » \\ Et comme ''\\'' reconnaît « \ », ''\\\.'' reconnaît « \. » Simple non ? ==== Le caractère de répétition ==== //Ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh, ça va mieux maintenant !// Quand on ne sait pas combien de fois un caractère va apparaître, on l'indique avec une étoile ''*'' ''Ah*'' reconnaît aussi bien « Ah » que « Ahhhhhhhhhhhhhhhhhhhhhhhhhh » ou même « A ». Quand on ne sait pas si un caractère va apparaître une fois ou jamais, on l'indique avec un point d'interrogation échappé ''\?'' ''Chevals\?'' reconnaît aussi bien « Cheval » que « Chevals ». Autre exemple : ''coq\?uille'' ==== Les ensembles de caractères possibles ==== Blah blah. ''Par[lt]ez'' reconnaît aussi bien « Parlez » que « Partez ». ''[a-z]'' reconnaît n'importe quelle lettre minuscule (non altérée)((ie. sans accent)) de l'alphabet. ''[A-Za-z]'' reconnaît n'importe quelle lettre (non altérée) de l'alphabet. ''[0-9\-]'' reconnaît les chiffres et le caractère « - ». **Remarque** : Il y a des classes de caractères déjà prédéfinies. Ainsi, blabla tableau honteusement pompé depuis http://www.commentcamarche.net/contents/php/phpreg.php3 (merci titia) : [:alnum:] caractères alphanumériques (équivalent à [A-Za-z0-9]) [:alpha:] caractères alphabétiques ([A-Za-z]) [:blank:] caractères blanc (espace, tabulation) [:ctrl:] caractères de contrôle (les premiers du code ASCII [:digit:] chiffre ([0-9]) [:graph:] caractère d'imprimerie (qui fait une marque sur l'écran en quelque sorte) [:print:] caractère imprimable (qui passe à l'imprimante ... tout sauf les caractères de contrôle) [:punct:] caractère de ponctuation [:space:] caractère d'espacement [:upper:] caractère majuscule [:xdigit:] caractère hexadécimal ==== Les caractères interdits ==== //101// Tout, sauf ça ! ''[^x]'' n'est pas un smiley, mais une expression rationnelle reconnaissant tout les caractères sauf « x » ''[^xy]'' reconnaît tous les caractères sauf « x » et « y » ''[^a-z]'' reconnaît tous les caractères sauf les lettres minuscules non altérées. ==== Début et fin de ligne ==== //Je suis l'α et l'ω.// ''^'' désigne un début de ligne ''$'' désigne une fin de ligne Ainsi, ''^Pouet'' reconnaîtra le motif ''Pouet'' s'il se trouve en début de ligne. TODO: le | disjonctif ==== Combinaisons ==== //20 000 lieues sous les mers.// TODO: Groupement \( \) ''[ab]*'' comme ''[ab]'' reconnaît aussi bien « a » que « b », ''[ab]*'' reconnaît aussi bien « aaaaaaaaa » que « abababbbbbbbbb » ou que « babbbaaa ». ''Abra*[ca]*dabrante\?'' reconnaît les chaînes commençant par « Abr », suivi par un nombre quelconque de « a », puis un nombre quelconque de « c » et de « a », suivis par « dabrant », suivi ou non par « e ». ===== TP Niveau 1 : Jouons avec grep / find / locate ===== (sur fiche annexe ?) ==== grep ==== grep regarde sur chaque ligne donnée à son entrée standard s'il trouve une regexp passée en argument. Si c'est le cas, la ligne est affichée, sinon, non. (à développer…) Soumettre une chaîne de caractère à grep filtrant suivant une regexp : echo "ma chaîne de caractère" | grep "ma[^î]*îne" ==== find ==== ==== locate ==== ==== Exos ==== Construire une regexp pour chacun des cas suivant - le mot « australopithèque » et son pluriel - les noms de domaine en « .fr » - les chaînes de 5 caractères - les mots de 5 lettres minuscules - les codes de carte bleue - les extensions de fichiers ===== TP Niveau 2 : Substituons avec Sed ===== (sur fiche annexe ?) Sed Substitution \1 Exos : url, etc.