======Les expressions rationnelles sous le jour des commandes ====== * Objet : maîtriser les expressions rationnelles basiques et étendues ainsi que les classes POSIX * Niveau requis : {{avisé}} * Commentaires : utiliser les expressions rationnelles basiques, étendues, les classes avec grep, grep -E, find, locate, expr, vi, sed et awk. =====Introduction ===== Il faut savoir en effet : * qu'il y a plusieurs types d'expressions rationnelles, * celles reposant sur la bibliothèque [[http://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended|POSIX]] * celles reposant sur la bibliothèque [[http://fr.wikipedia.org/wiki/PCRE|PCRE]].\\ Il s'agira ici de celle de la [[http://fr.wikipedia.org/wiki/Biblioth%C3%A8que_logicielle|la bibliothèque]] POSIX qui sont désignées souvent par les abréviations anglophones [[http://en.wikipedia.org/wiki/Regular_expression|REGEX ou REGEXP]] ; * qu'il y a différents programmes qui utilisent les expression régulières ; grep, expr, awk, sed, Perl, Tcl, Python, PHP, Java... Il s'agira ici de ceux utilisables en ligne de commandes GNU/Linux. * que certains des métacaractères reconnus par les shells UNIX (bash, ksh, csh, sh, etc.), sont homonymes avec certains caractères des //ER//, et qui plus est, ils servent le même objectif de fournir des motifs de recherche. Mais ils ne font pas partie de ce qu'on appelle les expressions rationnelles et ne doivent pas être confondus avec elles.\\ * que la syntaxe introduisant une //ER// n'est pas la même d'un programme de ligne de commandes GNU/Linux à l'autre. * Enfin, les différents programmes susceptibles d'utiliser toutes les //ER// de la bibliothèque REGEX, vi, expr, grep, egrep, find, locate, sed, awk, __transforment le contexte d'utilisation de l'//ER// et par conséquent, l'utilisation d'une même //ER// n'a plus le même effet d'un programme à l'autre__.\\ Ces deux derniers points sont rarement mis en avant, il est pourtant crucial de les soulever, pour des raisons autant pédagogiques, que philosophiques.\\ Le fondement en est simplement la certitude que //le dédain envers la diversité//, tandis que l'entendement est la puissance d'éprouver l'unité cachée sous tout genre de multiple, est une tentative qui s'ignore d'instrumentaliser la raison. **En bref, il s'agira de donner accès à l'utilisation des expressions rationnelles POSIX par la ligne de commandes GNU/linux.** ====Les types de REGEX ==== Il y en a trois : * expression rationnelle basique (ERb); appelées aussi "Basic Regular Expression" (BRE) * expression rationnelle étendue (ERe); appelées aussi "Extended Regular Expression" (ERE) * les classes POSIX (considérer soit comme ERb, soit comme ERe selon les programmes Les raccourcis (par exemples, retour à la ligne ''\n'', tabulation ''\t'') étant particuliers aux programmes, seront listés en complément. **Le détail des expressions régulières est présenté comme ceci :** - **[[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-communs-aux-erb-et-ere|les caractères communs aux ERb et ERe]].** - **les caractères spécifiques [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-specifiques-aux-erb|aux ERb]] et [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-specifiques-aux-ere|aux ERe]].** - **[[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#les-classes|les classes]]** ==== Panorama exhaustif des programmes GNU/Linux concernés par les expressions rationnelles=== * **expr** : **ERb**\\ pour la correspondance de chaîne de caractères avec une expression régulière. * **grep** : **ERb**\\ sélectionne par la //ER//, la ou les lignes d'un ou plusieurs fichiers comportant le motif. grep peut aussi rechercher les fichiers contenant le motif. * **grep -E** ou **egrep** : **ERe**\\ Même usage que grep * **find** : **ERb** en le précisant avec l'option **''-regextype "posix-basic"''** ou **ERe** en précisant avec l'option **''-regextype "posix-extended"''**\\ rechercher de fichier en fonction du motif spécifié par la //ER//. * **locate** : **ERb** avec l'option **''- -regexp''** ou **ERe** avec l'option **''- -regex''**\\ recherche de fichiers selon un motif dans la base de données. * **vi** : **ERb**\\ recherche et substitution de chaîne de caractères. * **sed** : **ERb**\\ par exemple, sélectionne, modifie les chaînes d'un fichier ou de l'affichage en se basant sur les colonnes. La //ER// permet de sélectionner quelle(s) colonne(s) est (sont) concernée(s). * **sed -r** : **ERe**\\ même usage que sed. * **awk**((c'est-à-dire **gawk**\\ ''whereis awk''\\ awk: /usr/bin/awk\\ ''ls -l /usr/bin/awk''\\ lrwxrwxrwx 1 root root 21 juin 8 18:43 /usr/bin/awk -> /etc/alternatives/awk\\ ''ls -l /etc/alternatives/awk''\\ lrwxrwxrwx 1 root root 13 juil. 13 18:41 /etc/alternatives/awk -> /usr/bin/**gawk**)) : **ERe**\\ sélectionne les colonnes, lignes, mots d'un fichier, et modifie l'affichage, le fichier, etc. en utilisant la //ER// comme condition de l'action qu'on choisit. Concernant chacun de ces programmes, je me limiterai strictement à leur utilisation des //ER//.\\ Pour plus de détail sur chacun d'entre eux, consulter la documentation à leur sujet.\\ ====Pour ne plus confondre "métacaractères" du shell et caractères des ER==== ===Rappel des caractères du shell servant au "globbing" === ^"métacaractères" ^significations ^exemples ^ |**Les métacaractères du shell (ou joker)** ||| |**''*''** |n'importe quelle chaîne de n'importe quels caractères |''ls b*''\\ **liste**\\ b\\ b2\\ bibi\\ bobo\\ bidule\\ ...\\ **mais pas**\\ titi\\ to\\ ... | |**''?''** |un caractère quelconque et un seul |''rm tit?'' **supprime**\\ tito\\ titi\\ tit~\\ ...\\ **mais pas**\\ tintin\\ titi.txt\\ ... | |**les "bracket expression" ** ||| |**''[ ]''** |un caractère cité dans la liste entre crochets |''echo [Tt][io]t[io]''((echo "Toto Tito toto toti tito loto" | echo [Tt][io]t[io]))\\ **affiche les fichiers**\\ Toto\\ Tito\\ toto\\ toti\\ ...\\ **mais pas**\\ loto\\ ... | |**''[ - ]''**\\ [a-z]\\ [A-Z]\\ [A-Z]\\ [0-9] |groupe de caractères |''head t[a-z]to''\\ **affiche**\\ titi\\ tito\\ toto\\ ...\\ **mais pas**\\ tOto\\ t5to\\ | =====Métacaractère ou caractère d'expression rationnelle ?===== Les commandes de recherche et d'édition de fichiers peuvent utiliser métacaractères et les caractères servant aux expressions rationnelles. ===Préparation=== * Exécuter cette ligne de commande : mkdir ERetCMD/ && cd ERetCMD/ && mkdir Dossier/ &&\ cd Dossier/ && touch milou && touch tata &&\ printf "Toto Titi toto titi tito\ndans\n" > titi &&\ printf "Toto Titi\ndent\n" > titi2 &&\ printf "toto aime le chocolat\n" > toto &&\ printf "Toto titi toto tito\n" > Toto.txt &&\ printf "un copain malin\nmodifiant cette page\n" > tintin &&\ printf "documentation\n" > titi1 && printf "." > titi1.txt &&\ printf "Il manque une option a tito\n" > tito &&\ printf "il a tout mangé.\n" > Toto1.txt ls milou tintin titi1 titi2 toto Toto.txt tata titi titi1.txt tito Toto1.txt Il est nécessaire d'avoir dossier, sous-dossier, et des fichiers ayant ou non du contenu pour s'exercer.\\ Mais pas d'inquiétude, tout ce qui a été créé ou qui le sera, peut être supprimer en une ligne: cd ~ && rm -vfR ERetCMD/ Le dossier et fichiers créés dans le dossier "ERetCMD" au cours de cette partie serviront aux exemples d'utilisation des expressions rationnelles avec chacun des programmes GNU/Linux. Mieux vaut ne pas les supprimer dès la fin de cette partie. ====grep==== **__Rappel sur grep__**\\ * __**Synopsis**__ : grep [OPTIONS] MOTIF [FICHIER...] grep [OPTIONS] [-e MOTIF | -f FICHIER] [FICHIER...] **''grep toto ~/Dossier/liste.txt''**\\ **''grep "toto" ~/Dossier/liste.txt''** >Les guillemets ne sont pas obligatoires pour un mot > Recherche le motif ''toto'' dans le fichier "liste.txt" **''grep toto ~/Dossier/liste.txt /Documents/téléphone.txt''**\\ > Recherche le motif ''toto'' dans les fichiers "liste.txt" et "téléphone.txt". **''grep "toto et titi" ~/Dossier/liste.txt" ''** > Les guillemets sont obligatoires lorsque MOTIF est une chaîne de caractères espacés d'un ou plusieurs espaces. * __**Options les plus courantes**__ : * -v affiche les lignes ne contenant pas MOTIF * -c compte le nombre de lignes contenant MOTIF * -n chaque ligne contenant MOTIF est numérotée * -r ou -R (récursif) recherche MOTIF dans tous les fichiers et sous-répertoires * -x ligne correspondant exactement à MOTIF * -l (par défaut) affiche le nom des fichiers qui contiennent MOTIF * -f (par défaut) pour plusieurs fichiers * -w recherche du MOTIF exact et non approchant **''grep -r -w Toto ~/''** * __L'étoile__ : Imaginons qu'on cherche __tous les fichiers commençant par "t"__ contenant le caractère "e".\\ grep -lR "e" t* tintin titi1 titi2 tito toto >Le motif entre guillemets ("e") concerne la recherche dans le contenu du fichier. C'est là qu'il faut placer l'expression rationnelle. Le motif "e" en est d'ailleurs une. >Le caractère "*" est le métacaractère qui signifie "__nom de fichier__ commençant par "Toto" avec n'importe quel autre caractère après ou rien après. * __Le caractère ?__ grep -E "[ae]n.?" titi? >Il faut grep -E car le **''?''** fait partie des expressions rationnelles étendues. >On peut aussi faire **''grep "[ae]n.\?" titi?''** car grep utilise par défaut les expressions rationnelles basiques qui nécessitent **''\''** devant certains caractères. titi1:documentation titi2:dent >On recherche dans les fichiers commençant par **''titi''** et suivi d'un seul caractère exactement (**''?''**), les mots comportant "an" ou "en".((Ici le caractère précédent est le "point", c'est-à-dire un caractère quelconque.)) >L'expression rationnelle décrit : une chaîne composée de "a" ou "e", suivi de "n", suivi d'un seul caractère ou non. * __Les crochets__ ont la même signification en tant que métacaractère et en tant que //ER// >Pour trouver dans les fichiers commençant par "T" ou "t" suivi de "i" ou "o" suivi d'un "t" suivi de "i" ou "o" suivi d'un caractère quelconque et un seul ; >Une chaîne comportant "T" ou "t" suivi de "i" ou "o" suivi d'un "t" suivi de "i" ou "o" : grep "[Tt][io]t[io]" [Tt][io]t[io]? grep "[Tt][io]t[io]" [Tt][io]t[io]? * __Le point n'est pas un métacaractère__ : > mais c'est un caractère des expressions rationnelles. >Ainsi la ligne signifie : rechercher un point littéral((le point étant un caractère des ER, il faut l'antislash pour qu'il soit lu comme un point littéral)) dans les fichiers commençant soit par "T" soit par "t", suivi de plusieurs caractères, et finissant par "txt" grep "\." [Tt]*.txt titi1.txt:. Toto1.txt:il a tout mangé. ==== find==== **__Rappel sur find__** : find **__Sans critère de recherche__** find affiche les fichiers du ou des répertoire(s) de recherche qu'on lui a donné en argument :\\ ''find /home/hypathie/Documents /home/hypathie/Bureau'' __**Les critères de recherche**__ : Utiliser les guillemets dans le critère de recherche est une bonne habitude à prendre car cela permet d’éviter les problèmes avec les caractères génériques du Shell : ''find ~ -name "*.mp3"'' * **-name** recherche sensible à la casse sur le nom du fichier * **-iname** recherche non sensible à la casse sur le nom du fichier * **-perm** recherche sur les droits d'accès du fichier((''-perm u=rwx'' (0700) ; ''-perm -u=r'' (-0400) => u=r ou u=rw ou u=rx ou u=rwx ou u=r,g=x… ; ''-perm /u=w,g=w,o=w'' => u=w ou g=w ou o=w ou u=w,g=w,o=w ou u=rw,g=rwx…)) * **-links** recherche sur le nombre de liens du fichier * **-user** recherche sur le propriétaire du fichier * **-group** recherche sur le groupe auquel appartient le fichier * **-type** recherche sur le type (''d''=répertoire, ''c''=caractère, ''f''=fichier normal, ''l''=lien, ''s''=socket)((lorsque l’on ne précise pas le -type à rechercher, la commande find recherchera des fichiers, des dossiers, des sockets, etc)) * **-size** recherche sur la taille du fichier ''M'' pour Méga Octets, ''G'' pour Giga Octets, ''c'' pour octets((+10M ; -10M ; 10M)) ou en nombre de blocs (1 bloc=512 octets) * **-atime** recherche par date de dernier accès en lecture du fichier * **-mtime** recherche par date de dernière modification du fichier * **-ctime** recherche par date de création du fichier Voir : [[http://qanuq.com/exploitez-la-puissance-de-la-commande-find/]] //Depuis le répertoire personnel ou le répertoire "~ERetCMD" ou même le répertoire "~/ERetCMD/Dossier/"// * __Étoile__ : find ~/ERetCMD/Dossier/ -name "toto*" /home/hypathie/ERetCMD/Dossier/toto * __Le point d'interrogation :__ find ~/ERetCMD/Dossier/ -name "titi?" /home/hypathie/ERetCMD/Dossier/titi1 /home/hypathie/ERetCMD/Dossier/titi2 * __Crochets :__ find ~/ERetCMD/Dossier/ -name "[Tt][io]t[io]?" /home/hypathie/ERetCMD/Dossier/titi1 /home/hypathie/ERetCMD/Dossier/titi2 ====locate ==== **__Rappel sur locate__**\\ locate **Options:**\\ * **-i** pour ignorer la casse majuscule ou minuscule * **-c** afficher seulement le nombre de résultat * **-n ** N'affiche que les n premiers résultats. * __Préparation :__ Se déplacer dans le répertoire "~/ERetCMD/" ; y créer les fichiers suivants en faisant : cd ~/ERetCMD/ && touch liste liste1 liste1-nom liste2\ liste2-nom liste3-erb-ere liste4-spec\ liste4-vim liste-class server-0.xkb smolski-exo-sed.txt\ sort1.txt sort2.txt sort3.txt\ image\ linux\ -\ 01.jpg image\ linux\ -\ 02.jpg\ image\ linux\ -\ 03.jpg img-perso-1.jpg img-perso-2.jpg ls Dossier img-perso-2.jpg liste2-nom server-0.xkb image linux - 01.jpg liste liste3-erb-ere smolski-exo-sed.txt image linux - 02.jpg liste1 liste4-spec sort1.txt image linux - 03.jpg liste1-nom liste4-vim sort2.txt img-perso-1.jpg liste2 liste-class sort3.txt Pour utiliser locate, qui fonctionne à partir de la base de donnée, faire un petit : updatedb pour effectuer les mises à jour, avant de lancer la recherche. * Rechercher les fichiers dont le nom est "un ou plusieurs caractères suivi de ".txt" : // Depuis n'importe où dans l'arborescence de fichiers :// locate ~/ERetCMD/*.txt /home/hypathie/ERetCMD/smolski-exo-sed.txt /home/hypathie/ERetCMD/sort1.txt /home/hypathie/ERetCMD/sort2.txt /home/hypathie/ERetCMD/sort3.txt ====sed==== Rappel sur sed\\ * Adressages * __sed utilise aussi les deux :__ Vérifier qu'on est bien au niveau du "~/ERetCMD/Dossier/" cd ~/ERetCMD/Dossier/ sed -r '/(a|e).*/s/a/A/' ti* > L'expression rationnelle est constituée de l'alternative ''(a|e)'' (la sous-chaîne "a" ou "e"), suivi d'un caractère quelconque zéro ou plusieurs fois. >Cela sera approfondit dans la partie [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#caracteres-specifiques-aux-erb-ou-caracteres-specifiques-aux-ere|Caractères spécifiques aux ERb ou caractères spécifiques aux ERe]] un copAin malin modifiAnt cette page Toto Titi toto titi tito dAns documentAtion . Toto Titi dent Il mAnque une option a tito ====awk ==== * __De même encore pour awk :__ Dans le dossier "~/ERetCMD/Dossier" créer les fichiers "smolski-awk.txt" et "smolski-sed.txt": touch smolski-sed.txt && cat >> smolski-sed.txt < touch smolski-awk.txt && cat >> smolski-awk.txt < * Utilisation d'une ER et de métacaractère avec awk : awk '$3 ~ /(e|E)/' smolski-* >Affiche les lignes dont la troisième colonne comporte un "e" ou un "E" de TOUS les fichiers du répertoire "~/ERetCMD/Dossier" commençant par "smolski-". >Le caractère ''~'' (tilde) est un opérateur de correspondance relevant de la commande awk. >Il permet de tester la correspondance entre la variable ''$3'' et l'expression rationnelle encadrée de ''/'' (''/(e|E)/''). Voir [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#awk-et-les-caracteres-communs-aux-erb-et-ere|awk et les expressions rationnelles]] 3 3 CAMILLE M 7 4 3 CHLOE F 12 6 3 CLEMENT M 7 7 3 EMMA F 6 8 3 THEO M 8 toto préfère les Fraises. titi les cerises. Pour vi (vim), il faut avoir édité le ou les fichiers pour utiliser les expressions rationnelles, mais on peut __utiliser les métacaractères pour ouvrir plusieurs fichiers en même temps__.\\ Par exemple en étant au niveau du fichier "~/ERetCMD/Dossier" : vim smolski-* Les fichiers "smolski-awk.txt" et "smolski-sed.txt" seront ouverts.\\ Et pour passer de l'un à l'autre : on tape au clavier '':next'', pour passer au second, si on se trouve devant le premier;\\ ou '':previous'', si l'on se trouve devant le second et qu'on veut revenir au premier. D'autres exemples d'utilisation des expressions rationnelles avec [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#l-editeur-de-texte-vi-n-utilise-aussi-que-les-erb|vim]] seront donnés. **Puisque tout est bien clair, nous pouvons aller plus loin, et présenter le détail des expressions rationnelles ainsi que leur utilisation avec les programmes GNU/Linux. Cela permettra, non seulement de distinguer ERb, ERe et classes, mais encore d'en apprécier les différences.** 8-) =====Caractères communs aux ERb et ERe===== * Certains caractères sont communs au ERb et ERe.\\ Il est possible de les regrouper car toutes les commandes qui permettent de se servir des expressions rationnelles, reconnaissent tous les caractères communs aux ERb et ERe. * Certaines commandes les utilisent soit en tant que ERb, soit en tant que ERe :\\ il s'agit de **''grep''** ; **''sed''** ; **''locate''** ; et **''find''**. * **''awk''** (gawk) les utilise en tant que ERe. * **''vi''** (vim) et **''expr''** les utilisent en tant que ERb. ^expressions ^Modèles reconnus ^ |**c** | Tout non métacaractère c.| |**''\''** |Échappement du caractère spécial.\\ Par exemple **''\.''** sélectionne un point littéral.| |**''^''** |Test effectué au début de la chaîne.| |**''$''** |Test effectué à la fin de la chaîne.| |**''.''** |Tout caractère sauf une fin de ligne.| |**'' *''** |Zéro à n chaînes consécutives validées par l’expression régulière r.| |**'' \< ''** |début d'un mot (caractères pouvant faire partie de [A-Z-z0-9]| |**'' \> ''** |Fin d'un mot| |**''[liste_de_caractères]''** |Un caractère cité dans la liste | |**''[^liste_de_caractères]''** |Un carcatère qui n'est pas dans la liste | ====La commande grep et les caractères communs aux ERb et ERe==== Sans option ou avec l'option -G, grep utilise les expressions rationnelles basiques. -G, --basic-regexp Interpréter le MOTIF comme une expression rationnelle simple C'est le comportement par défaut. Pour l'utilisation de grep (grep -G ou grep -E) avec soit les caractères spécifiques aux ERb, soit les caractères spécifiques aux ERe, voir [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#grep-e-egrep-et-les-caracteres-specifiques|"grep -E (egrep) et les caractères spécifiques aux ERe"]]. ===Préparation === * Dans le répertoire "~/ERetCMD/" inscrire le contenu suivant dans le fichier "liste1-nom" : cd ~/ERetCMD/ && cat >> liste1-nom << EOF 1 2 Francine 2 3 Édith 3 4 Géraldine 123 AAAAAA tout le monde partout toutefois 4 5 Béatrice 5 6 Christelle 5 7 Dorothée 6 8 Amanda EOF >La dernière ligne du fichier est vide. ===Le caractère début de ligne ^ === grep "^4" liste1-nom 4 5 Béatrice ===Le caractère fin de ligne $ === grep "e$" liste1-nom 1 2 Francine 3 4 Géraldine tout le monde 4 5 Béatrice 5 6 Christelle 5 7 Dorothée * pour sélectionner une ligne vide : grep "^$" liste1-nom ===Le point=== grep ".dith" liste1-nom 2 3 Édith ===L'étoile=== grep "A*" liste1-nom 1 2 Francine 2 3 Édith 3 4 Géraldine 123 AAAAAA tout le monde partout toutefois 4 5 Béatrice 5 6 Christelle 5 7 Dorothée 6 8 Amanda >Encore une fois, il ne s'agit pas du métacaractère. >Étoile signifie "zéro ou plusieurs 'A'" ; **zéro** fois aussi. Donc toutes les lignes dépourvues du caractère "A" apparaissent, __y compris la ligne vide__. * __Autre exemple :__ grep "123 A*" liste1-nom 123 AAAAAA ===Les crochets=== grep "[43]" liste1-nom 2 3 Édith 3 4 Géraldine 123 AAAAAA 4 5 Béatrice >Les lignes comportant 4 ou 3 ===Le caractère d'exclusion d'une liste [^ ]=== >Chaîne qui commence ni par 1, ni par 2, ni par aucun des caractères entre crochets. grep "^[^12345678]" liste1-nom tout le monde partout toutefois *Chaîne qui ne se termine pas par l'un des caractères de l'intervalle. grep "[^a-z]$" liste1-nom 123 AAAAAA ===Le caractère début de mot \<=== grep "\ tout le monde toutefois ===Le caractère fin de mot \>=== grep "fois\>" liste1-nom toutefois * __Et un mot exactement \ :__ grep "\" liste1-nom tout le monde ====La commande find et les caractères communs aux ERb et ERe==== -regextype type Définir la syntaxe des expressions rationnelles des tests -regex et -iregex qui seront indiqués plus loin sur la ligne de com‐ mande. Les types actuellement implémentés sont emacs (type par défaut), posix-awk, posix-basic, posix-egrep et posix-extended. Avec find, il faut toujours une option pour utiliser une //ER//.\\ * Pour une expression rationnelle basique :\\ find -regextype "posix-basic" -regex "son-expression-rationnelle-basique" * Pour une expression rationnelle étendue :\\ find -regextype "posix-extended" -regex "son-expression-rationnelle-étendue" * Il faut aussi prévenir find, qu'on va utiliser une ER avec :((de même qu'on prévient qu'on cherche un motif en respectant la casse avec ''-name'')) * **''-regex ER''** * **''-iregex motif''** : Semblable à -regex, pour ne pas tenir compte de la casse (ne pas différencier les majuscules et les minuscules). * Il s'agit d'une correspondance sur __le chemin complet__.\\ Pour représenter un chemin absolu quelque soit-il, il faut ajouter en début d'expression **''.*''**. Je ne donnerai ici quelques exemples d'utilisation des caractères communs aux ERb et ERe, en tant que caractères ERb, afin d'illustrer l'utilisation de find avec l'option ''-regextype "posix-basic''.\\ Pour l'utilisation des caractères spécifiques aux ERb ou des caractères spécifiques aux ERe avec find, voir : [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#find-et-les-caracteres-specifiques|"find et les caractères spécifiques aux ERe"]].\\ * Rappel des fichiers contenus dans "~/ERetCMD/": ls Dossier img-perso-2.jpg liste2-nom server-0.xkb image linux - 01.jpg liste liste3-erb-ere smolski-exo-sed.txt image linux - 02.jpg liste1 liste4-spec sort1.txt image linux - 03.jpg liste1-nom liste4-vim sort2.txt img-perso-1.jpg liste2 liste-class sort3.txt * __Caractères point et étoiles :__ find -regextype "posix-basic" -regex ".*/li.*m" ./liste2-nom ./liste1-nom ./liste4-vim >Le premier groupe de ''.*'' décrit le chemin du ou des fichiers dont le nom correspond à une chaîne commençant par "li", suivi de plusieurs caractères (deuxième groupe ''.*''), puis d'un "m". >La même commande lancée depuis un répertoire plus en amont dans la hiérarchie, par exemple, depuis le répertoire personnel de l'utilisateur,et non depuis le répertoire parent des fichiers : find -regextype "posix-basic" -regex ".*/li.*m" ./liste2-nom ./liste1-nom ./liste4-vim ./.config/libreoffice/3/user/gallery/sg100.thm ./.config/libreoffice/3/user/gallery/sg30.thm * __Avec les crochets :__ >Dans le répertoire "~/ERetCMD/", les fichiers comportant un "e" ou un "s", plusieurs caractères, un point littéral (\.), plusieurs caractères : find -regextype "posix-basic" -regex ".*/[es].*\..*" ./Dossier/smolski-sed.txt ./Dossier/smolski-awk.txt ./smolski-exo-sed.txt ./server-0.xkb ./sort3.txt ./sort1.txt ./sort2.txt ====La commande locate et les caractères communs aux ERb et ERe==== Pour utiliser les //ER// avec locate, il faut dans tous les cas une option.\\ Les caractères communs aux ERb et ERe, peuvent être utilisés avec l'une ou l'autre de ces options : * __Pour utiliser les ERb, il faut utiliser l'option__ : --regexp REGEXP Search for a basic regexp REGEXP. No PATTERNs are allowed if this option is used, but this option can be specified multiple times. * __Pour utiliser ces mêmes caractères en tant que ERe il faut utiliser l'option__ : --regex Interpret all PATTERNs as extended regexps Sans l'une ou l'autre de ces options, locate reconnaît le caractère ''*'' comme un métacaractère du shell.\\ => Encore une fois, si on choisit d'utiliser les ERb, il faudra un antislash pour utiliser [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-specifiques-aux-erb|les caractères spécifiques aux ERb]] et ce sera inutile si on choisit les ERe. Voir [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#locate-et-les-caracteres-specifiques|"locate et les caractères spécifiques"]] * Contrairement à find, __il n'est pas nécessaire que la ER corresponde au chemin absolu d'un fichier__.\\ Mais la quantité de réponses peut être très élevée, et si l'on a une idée du répertoire dans lequel se trouve le fichier recherché, il peut plus confortable de le préciser.\\ On peut aussi filtrer le retour avec grep.\\ * Enfin, avec l'utilisation de locate, le caractère début (^) est inusité.\\ En effet, avec une commande qui recherche des noms de fichier, la seule possibilité serait **''^/''**. Or locate permet justement de ne pas avoir à donner le chemin absolu du fichier recherché. L'utiliser ne ferait qu'allonger inutilement l'expression régulière !\\ updatedb * __Étoile et point :__ >Éviter ce qui suit qui donne un retour de plusieurs pages : locate --regexp '/home.*[Tt]o.*' > On peut faire par exemple : locate --regexp '/home.*[Tt]o.*' | grep "/Dossier/" /home/hypathie/ERetCMD/Dossier/Toto.txt /home/hypathie/ERetCMD/Dossier/Toto1.txt /home/hypathie/ERetCMD/Dossier/tito /home/hypathie/ERetCMD/Dossier/toto * __Caractère fin de ligne $ :__ locate --regexp '/home.*/Dossier/[Tt]o.*\.txt$' /home/hypathie/ERetCMD/Dossier/Toto.txt /home/hypathie/ERetCMD/Dossier/Toto1.txt * __Le caractère début de mot ''\<'' :__ locate --regexp '.*\ /home/hypathie/ERetCMD/smolski-exo-sed.txt /home/hypathie/ERetCMD/Dossier/smolski-awk.txt /home/hypathie/ERetCMD/Dossier/smolski-sed.txt ====La commande sed et les caractères communs aux ERb et ERe==== Pour les caractères considérés ci-dessus, ''. ; *, ^, $, [liste de caractères], [^liste de caractères], \<, \>'',\\ __il en va de même pour la commande sed que pour la commande grep__.\\ Je ne donnerai que quelques exemples.\\ Il est à noter que sans l'option -i, les exemples ne modifieront pas le fichier.\\ En étant au niveau du répertoire : "~/ERetCMD/". * __Les caractère début et fin de ligne :__ Par exemple, pour supprimer la ligne vide à l'affichage : sed '/^$/ d' liste1-nom * __Le caractère étoile :__ Par exemple, substituer "AAAAAA" par abc sed '/A*/s/AAAAAA/COUCOU/' liste1-nom 1 2 Francine 2 3 Édith 3 4 Géraldine 123 COUCOU tout le monde partout toutefois 4 5 Béatrice 5 6 Christelle 5 7 Dorothée 6 8 Amanda * __Le caractère fin de mot :__ Par exemple, tout supprimer sauf (''!'')((relève du vocabulaire de sed, et n'est pas un caractère appartenant aux ER)) la ligne correspondant à un mot finissant par "fois" : sed '/fois\>/ !d' liste1-nom toutefois ===Attention au sens global de la ER donné par la commande=== Si la signification des caractère est la même, l'action de la commande modifie "la phrase", ou le sens global de la //ER//.\\ Comparer l'usage des [^ ] de grep avec ce qui suit : echo "12 f 6 7" | sed 's/^[^12345678]/coucou/g' 12 f 6 7 >Il ne se passe rien car avec sed la signification de la //ER// est : "substitue le caractère de début de la ligne qui ne commence pas par l'un des caractères '1234567'". >sed ne cherche pas comme grep une chaîne ou un cataère qui "ne commence pas par l'un des caractères '1234567'", et ne substituerait pas "f" de cette manière. >Ainsi : echo " 12 f 6 7" | sed 's/[^1-7]/X/g' X12XXX6X7 >Le sens de la //ER// est "substitue tout ce qui n'est pas 1, 2, 3, 4, 5, 6, 7 par "X" > Y compris les espaces ! > Il ne faut donc pas s'imaginer que sed utilise une version non posix des //ER//, telle que la littérature à son sujet l'alimente parfois. > Ce n'est que pour ce qui concerne les implantations GNU qui ne sont pas posix, que sed présente quelques bizarreries. > Rien d'obscure et pas d'obscurantisme, tout reste logique, à condition de savoir en changer... C'est là ce qui rend passionnant l'utilisation d'un méta-langage, la possibilité de la différence par delà l'identité des éléments, au moyen du contexte ! ====awk et les caractères communs aux ERb et ERe ==== La commande awk travail sur les colonnes, les lignes, les mots, et constitue un langage de programmation. Je ne rappellerai pas toutes les fonctions de awk mais présenterai seulement comment utiliser les //ER// pour une utilisation basique de cette commande.\\ L'usage le plus simple d'awk consiste à utiliser une //ER// pour sélectionner une chaîne.\\ Le contenu des champs sont enregistrés dans les variables $1, $2, $3, ..., correspondant aux colonnes 1, 2, 3, ...\\ Avec awk la //ER// est encadrée par des slash ''/ER/''. * __L'étoile :__ echo "123 AAAAAA" | awk '/A*/{print $2}' AAAAAA >Notez qu'il s'agit bien du caractère ''*'' qui signifie "une ou plusieurs fois 'A', et non du métacaratère ''*''. >Notez encore que cet exemple est un peu surfait. Il ne sert qu'à vérifier si la ER est juste, et à rappeler la syntaxe d'utilisation d'une //ER// avec awk. C'est que awk ne sert pas à vérifier l'exactitude d'une ER. Au contraire la ER sert de condition (correspondance de la chaîne AAAAAA avec ''A*'' ) pour effectuer une action (ici imprimer, c'est-à-dire afficher la colonne n°2). > Néanmoins, cet exemple permet d'insister encore une fois : il est important de bien comprendre que la signification globale d'une //ER// dépend du contexte créé par les commandes.\\ ===Comparaison de sed et d'awk === Modifions l'exemple ci-dessus, afin de comparer l'utilisation d'une //ER// dans le contexte de awk avec celui de sed. * Rappel : echo " 12 f 6 7" | sed 's/[^1-7]/X/g' X12XXX6X7 > substitution par "X" de tout ce qui n'est pas 1, 2, 3, 4, 5, 6, 7 * Même exemple avec sed : echo "12 f 6 7" | awk '/[^12345678]/{print $2}' f >Afficher le champ n°2 (''$2'') si la //ER// ( "tout ce qui n'est pas 1, 2, 3, 4, 5, 6, 7") est vraie. Ce qui rend difficile l'utilisation des //ER// n'est peut-être pas de savoir "traduire" une expression littérale par l'association de plusieurs caractères symboliques. C'est bien plutôt la "mouvance" de l'effet de cette "traduction", effet qui n'est pas le même selon telle ou telle commande utilisée.\\ Chaque commande crée un contexte différents qui détermine l'usage des //ER//.\\ Si l'utilisation des //ER// est souvent déprécié, c'est pour une bonne part parce que leurs différents contextes ne sont jamais mis en confrontation. Mais une fois ces contextes précisés, et une fois s'être exercé à passer de l'un à l'autre, l'utilisation des //ER// devient bien plus facile. * __Le caractère début de ligne (^) :__ Visualisation du fichier "liste1-nom" dont la dernière ligne est vide : cat liste1-nom 1 2 Francine 2 3 Édith 3 4 Géraldine 123 AAAAAA tout le monde partout toutefois 4 5 Béatrice 5 6 Christelle 5 7 Dorothée 6 8 Amanda awk '$1 ~ /^4/' liste1-nom >Affiche la ligne ou les lignes dont la colonne n°1 correspond à la //ER// ("qui commence par 4"). 4 5 Béatrice >L'action par défaut est print, s'il aucune action n'est mentionnée et que la condition est vraie. Le caractère tilde **''~''** est un opérateur de correspondance entre une //ER// et une variable.\\ Il ne s'agit pas du tilde qui symbolise le répertoire personnel de l'utilisateur.\\ Et ce n'est pas un caractère qui fait partie des caractères des expressions rationnelles.\\ L'opérateur de correspondance appartient à awk, et fait partie des [[utilisateurs:hypathie:tutos:awk-synthese#operateurs-de-tests|opérateurs de tests]] **''<''** ; **''>''** ; **''==''** ... * __Caractère fin de ligne ($) :__ awk '$3 ~ /ce$/' liste1-nom 4 5 Béatrice * __Caractères point et étoile :__ awk '$3 ~ /.d.*/' liste1-nom > Affiche la ou les lignes dont le troisième champ (colonne) comporte une chaîne correspondant à "un caractère (**''.''**), suivi d'un **''d''**, suivi d'un ou plusieurs caractères (**''.*''**). 2 3 Édith 3 4 Géraldine tout le monde 6 8 Amanda * __Les crochets :__ awk '$3 ~/t[h]/' liste1-nom >Affiche la ou les lignes dont la chaîne correspond à la //ER// "t" ou "th" 2 3 Édith 5 7 Dorothée * __Exclusion [^ ] :__ awk '$1 ~ /^[^12345678]/' liste1-nom tout le monde partout toutefois * ou avec la __non-correspondance__ **''!~''** propre à awk : awk '$1 !~ /^[12345678]/' liste1-nom tout le monde partout toutefois > La seule différence entre ''$1 ~ /^[^12345678]/'' et ''$1 !~ /^[12345678]/'', c'est que la deuxième //ER// affichera une ligne vide, et non la première. * __Début et fin de mot :__ awk '$1 ~ /fois\>/' liste1-nom toutefois ====La commande expr n'utilise que ERb==== ===Syntaxe === expr chaîne-de-caractères : expression-rationnelle-basique * La commande expr utilise l'opérateur **'':''** pour mettre en correspondance une chaîne de caractères avec une //ER//. * Si le nombre de caractères de la chaîne correspond à l'ERb, alors expr affiche ce nombre à l'écran. * Si la correspondance décrite ci-dessus est vraie, le code de retour est 0 (zéro). * Si elle est fausse, expr retourne 0 (zéro) pour "zéro correspondance) et le code de retour est 1 (un). * L'expression rationnelle est comparée par rapport au début de la variable, le caractère **''^''** est toujours implicite. * Si une partie de l'expression rationnelle est mémorisée avec **''\( \)''** la commande expr affiche dans le terminal la partie correspondante. ===Exemples === * crochet, étoile, fin de ligne : var=123 expr "$var" : '[0-9]*$' 3 >"3" ne doit pas être confondu avec un code de retour, c'est le nombre de caractères de la variable qui correspondent à //ER//. echo $? 0 >La correspondance est vraie : code de retour "0". >La variable comporte bien 3 caractères 1, 2, et 3 et non le chiffre "123"; il s'agit d'une comparaison sur chaîne de caractères. * ER qui ne correspond pas à la chaîne de la variable : var="les bonbons, c'est bon" expr "$var" : 'bons\>' 0 >zéro est le nombre de caractère correspondant echo $? 1 > Le chiffre "1" est le code de retour : pas de correspondance, donc code d'erreur. * sous chaîne avec caractère fin de mot : var="les bonbons, c'est bon" expr "$var" : '\(.*bons\>\),' les bonbons >Demander le code de retour est inutile, la ER est forcément juste, s'il y a affichage de la sous-chaîne correspondante. À moins d'en avoir besoin lors d'une utilisation de expr dans un script shell s'en servant pour un test. ====L'éditeur de texte vi n'utilise aussi que les ERb ==== ===Préparation du fichier "liste4-spec" === * Donner le contenu suivant au fichier "liste4-spec" en faisant : cd ~/ERetCMD/ && cat >> liste4-spec < Modes utilisés dans ce qui suit :\\ * **Le mode normal**: celui dans lequel vous êtes à l'ouverture du fichier. Il permet de taper des commandes. * Par exemple, la commande **:q!** pour sortir sans enregistrer ; * la commande **:wq** pour enregistrer et sortir * **Le mode insertion**: Ce mode permet d'insérer les caractères que vous saisissez à l'intérieur du document. Pour passer en mode insertion, il suffit d'appuyer sur **la touche "i"** ; touche "Échap" pour en sortir. * Pour tester ce qui suit si vous ne connaissez pas vi ou vim :\\ *Après [[doc:editeurs:vim:vim#installation|installation de vim]], créer un fichier, par exemple "liste4-vim" : '' vim liste4-vim '' * Copier le contenu de "liste4-vim" ci-dessus ; * Pour coller dans le fichier "liste4-vim" édité avec vim : * touche + touche (cela fait que l'on est en mode insertion) * sortir du mode insertion : touche "Échap" * enregistrer et sortir : '' :wq '' et touche * Pour apprendre les rudiments de l'utilisation de vim (et donc de vi), après l'installation de vim : vimtutor -> Pour y ajouter l'utilisation des //ER//, suivre ce qui suit. * Éditer le fichier "liste4-vim" en faisant : vi liste4-spec ou vim liste4-spec {{http://pix.toile-libre.org/upload/original/1407922486.png?400}} ===Syntaxe d'utilisation des ER=== * **recherche** en __mode interactif tapez (/)__ : /expression-rationnelle-basique * /chaîne ou ER - rechercher ce qui correspond à chaîne ou les chaînes correspondant à ER * n - rechercher l'occurrence suivant de la chaîne * N - rechercher l'occurrence précédente de chaîne * **substitution d'une occurrence** (depuis le mode interactif passer en __mode commande (:)__ : :[adresse[,adresse]]s/expression-rationnelle-basique/remplacement/[drapeau] * **substitution sur tout le texte**, ou une portion __en mode commande (:)__ : :adresse%s/chaine_a_remplacer/chaine_de_remplacement/ *g - drapeau - remplacer toutes les occurrences de le //ER// (si cette option n'est pas utilisée, vi substituera que la prochaine occurrence du motif) *c - drapeau - confirmer le remplacement *i - drapeau - ignorer la casse (prend en compte toutes les occurrences de la chaîne en majuscules ou en minuscules) ===Exemples de recherches === * __Le caractère début de ligne ^ __ /^chose On appuie sur la touche shift+: pour inscrire ''/'', on inscrit sa ER, on valide avec la touche "entrée". vi ou vim surligne toutes les occurrences de "chose" qui sont en début de ligne. :nohlsearch Pour retirer la surbrillance de la recherche. * __Le caractère fin de ligne $__ /chose$ On valide avec entrée, et '':nohlsearch'' pour effacer ===Exemples de substitution=== * __Crochets :__ :s/[Ss]/XXX/g >Substitue les caractères "S" ou "s" à la ligne du curseur et surligne toutes les occurrences potentiellement substituables. > **'':nohlsearch''** pour retirer la surbrillance. >puis pour annuler la substitution "Échap" (pour être sûr de ne pas être en mode insertion), puis appuyer sur la lettre "u" ("u" pour annuler un seul changement, ("U" pour annuler plusieurs changements). * __idem sur tout le texte :__ :1,$s/[Ss]/XXX/g >"1,$" est l'adressage qui signifie de la première ligne à la fin. * __Sous-chaîne avec parenthèses et accolades :__ /\([0-9]\{3\}.\)\{2\}\. >Vi ou vim surligne à la ligne 9 (comportant "123.3456.abc") la sous-chaîne **''123.3456.''**. =====Caractères spécifiques aux ERb et ERe ===== Je présenterai d'abord les commandes qui utilisent uniquement les ERb, c'est-à-dire, celles qui n'ont pas besoin d'une option pour utiliser les expressions rationnelles et qui n'utilisent que les expressions rationnelles basiques, et donc forcément les caractères spécifiques aux ERb.\\ Il s'agit de **''expr''** et **''vi''**.\\ Je présenterai ensuite les commandes "à option" qui utilisent tous les caractères spécifiques aux ERb, mais qui peuvent aussi utiliser ces mêmes caractères((parenthèses, accolades, +, ? et |)) sans antislash avec les ERe.\\ Ainsi tous les caractères des expressions rationnelles auront été abordés ainsi que leurs divers contextes d'utilisation. Il ne restera plus qu'à présenter [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#les-classes|les classes]]. ====Caractères spécifiques aux ERb ==== Toutes les commandes utilisant les expressions rationnelles basiques utilisent les caractères énumérés ci-dessous.\\ La commande **''expr''** n'utilise que ceux-ci.\\ ^expressions ^Modèles reconnus ^ |**''\{m\}''** | m fois le caractère précédent | |**''\{m,\} ''** | au moins m fois le caractère précédent | |**''\{m,n\} ''** | entre m et n fois le caractère précédent | |**''\(ERb\)''** | mémorisation d'une ERb | |**''\1, \2, ...''** | Rappel de mémorisation | Les commandes **''grep''** (ou **''grep -G''**) ; **''find -regextype "posix-basic" ''** ; **''locate --regexp''** ; **''sed''**; **''vi''** utilisent en plus ces caractères ci-dessous : ^ ^ ^ |**''\?''** | zéro ou une fois l'élément précédent | |**''\+''** | une ou plusieurs fois l'élément précédent | |**''\|''** | alternative | -> Le caractère **''\''** donne une signification spéciale aux parenthèses et accolades, ?, +, | au lieu de les rendre littérales.\\ Mais il permet de rendre littéraux les autres caractères des ERb, par exemple ''\.'' permet de sélectionner un point. ====Caractères spécifiques aux ERe ==== Les caractères spécifiques aux ERe sont utilisables avec les commandes : **''grep -E''** ; (ou **''egrep''**) ; **''find -regextype "posix-extended" ''** ; **''locate --regex''** ; **''sed -r''** et **''awk''**((alias gawk)).\\ Bien évidemment tous [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-communs-aux-erb-et-ere|les caractères communs aux ERb et ERe]] sont utilisables avec ces commandes et ces options. ^expressions ^ Modèles reconnus ^ |**''?''** | zéro ou une fois le caractère ou le regroupement précédent | |**''+''** |une à n fois le caractère ou regroupement précédent | |**''{m}''** |m fois le caractère précédent | |**''{m,}''** | m fois le caractère précédent | |**''{m,n}''** | entre m et n fois le caractère précédent | |**''( er1)''** | regroupement | |**''er1|er2|er3''** | alternative | |**''(er)+''**|Une ou plus de une chaîne(s) consécutive(s) validée(s) "er".| |**''(er)*''**|zéro ou plus de zéro chaîne(s) consécutive(s) validée(s) par "er" | |**''(er)?''**|une chaîne bulle ou toute chaîne validée par "er".| |**''[c1c2...]''**|Tout caractère expressément listé entre les crochets.| |**''[^c1c2...]''**|Tout caractère excepté ceux qui sont expressément listés entre les crochets.| |**''[c1-c2]''**|Tout caractère appartenant à l’intervalle c1 c2, bornes comprises.| |**''er1|er2''**|Toute chaîne de caractères validée soit par er1 soit par er2.| |**''(er)(er)''**|Toute chaîne validée par l’expression er, chaîne vide exclue.| |**''(er1)(er2)''**|Toute chaîne de caractères de type AB, dans laquelle l’expression régulière er1 valide A et l’expression régulière er2 valide B.\\ Avec awk uniquement| =====Les commandes expr et vi et les caractères spécifiques aux ERb ===== ====La commande expr n'utilise que ERb==== __ **Rappel :**__\\ * Soit le fichier "liste4-spec" : cat liste4-spec gdd:a:aa:aaa:aaaa:aaaaaa:aaaaaaaa T5c Kc5 T5 c E2* abcd 7 9Abcd 7 1AAA.AAA.bcdef aBcd6a 123* abc2356.99 73000|Savoie 123456 1234567 index-tel|04|Rhône-Alpe -15 +36 5687 {15} exemple{36} il y a un truc et un truc et encore un truc et une chose choses et trucs ne font pas bon ménage 123.3456.abc trucschosetruc tructructrucs chosechosechose * Syntaxe : expr chaîne-de-caractères : expression-rationnelle-basique * **''expr''** utilise tous les [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-communs-aux-erb-et-ere|caractères communs aux ERb et ERe]] * mais elle n'utilise que les caractères spécifiques aux ERb ci-dessous : |**''\{m\}''** | m fois le caractère précédent | |**''\{m,\} ''** | au moins m fois le caractère précédent | |**''\{m,n\} ''** | entre m et n fois le caractère précédent | |**''\(ERb\)''** | mémorisation d'une ERb | |**''\1, \2, ...''** | Rappel de mémorisation | ===Exemple === * sous-chaîne et quantificateur accolades : var=123.456. expr "$var" : '\([0-9]\{3\}.\)\{2\}' 456. > expr affiche la sous-chaîne "456." *Le caractère **''*''** est gourmand : var="hypathie|00 rue Debian-facile|01011|ici" expr "$var" : '\(.*\)|' hypathie|00 rue Debian-facile|01011 ====L'éditeur de texte vi et les caractères spécifiques aux ERb==== **'' vi''** (vim) utilise tous [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-communs-aux-erb-et-ere|les caractères communs aux ERb et ERe]], tous [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes?&#caracteres-specifiques-aux-erb|les caractères spécifiques aux ERb]], y compris ceux ci-dessous (comme "les commandes à option" permettant de choisir le type //ER//): |**''\?''** | zéro ou une fois l'élément précédent | |**''\+''** | une ou plusieurs fois l'élément précédent | |**''\|''** | alternative | * Reprise du fichier "liste4-vim" : vi liste4-vim ou vim liste4-vim {{http://pix.toile-libre.org/upload/original/1407922486.png?400}} ===utilisation de \| === /c\|t ->Une image vaut mieux qu'une description :\\ {{http://pix.toile-libre.org/upload/original/1407937898.png?400}} ===Utilisation de \? === /\.[0-9]\? -> Là aussi :\\ {{http://pix.toile-libre.org/upload/original/1407857157.png?400}} ===Utilisation de \+ === /[A-Z]\+ -> Là aussi :\\ {{http://pix.toile-libre.org/upload/original/1407856299.png?400}} La substitution sous vi et vim est très proche de sed. Je ne développerai pas d'avantage. \\ En plus des ERb, vi et vim utilisent quelques raccourcis.\\ * \d - chiffres de 0 à 9 * \n - nouvelle ligne Pour plus de détail sur vi et vim et l'utilisation des REGEX, voir :\\ *[[http://www.olivierpons.fr/2010/08/05/vim-expressions-regulieres-rechercher-remplacer-memo/]]\\ *[[http://switzernet.com/3/public/110324-training-vi-regex/]] =====Caractères spécifiques aux ERb ou caractères spécifiques aux ERe ===== **grep**, **sed**, **find**, **locate** utilisent soit les expressions rationnelles basiques, soit les étendues.\\ Précisons à cette occasion, comment s'utilisent les caractères spécifiques des expressions rationnelles étendues. **awk** (gawk) utilise seulement les expressions rationnelles étendues; voir [[utilisateurs:hypathie:tutos:erb-et-ere-par-le-contexte-des-commandes#awk-les-ere-et-les-classes|awk, les ERe et les classes]] ===Préparation=== * Soit le fichier "liste4-spec": gdd:a:aa:aaa:aaaa:aaaaaa:aaaaaaaa T5c Kc5 T5 c E2* abcd 7 9Abcd 7 1AAA.AAA.bcdef aBcd6a 123* abc2356.99 73000|Savoie 123456 1234567 index-tel|04|Rhône-Alpe -15 +36 5687 {15} exemple{36} il y a un truc et un truc et encore un truc et une chose choses et trucs ne font pas bon ménage 123.3456.abc trucschosetruc tructructrucs chosechosechose ==== grep -E (egrep) et les caractères spécifiques==== Avec l'option -E grep utilisent les expressions rationnelles étendues.\\ La commande egrep et un équivalent. Pour les caractères : **'' [ ] { } ? + |''**\\ il possible avec grep d'utiliser aussi les caractères spécifiques aux ERb.\\ Par exemple :\\ grep "1A\{3\}\.A\{3\}\..*" liste4-spec ou grep -G "1A\{3\}\.A\{3\}\..*" liste4-spec 7 1AAA.AAA.bcdef aBcd6a 123* -> mais ne pas oublier l'antislash devant les accolades !\\ ===Parenthèses === grep -E "( [0-9]{4})" liste4-spec -15 +36 5687 {15} exemple{36} ===le caractère précédent de "n" à "m" fois :=== grep -E "[0-9]{1,3}" liste4-spec T5c Kc5 T5 c E2* abcd 7 9Abcd 7 1AAA.AAA.bcdef aBcd6a 123* abc2356.99 73000|Savoie 123456 1234567 index-tel|04|Rhône-Alpe -15 +36 5687 {15} exemple{36} 123.3456.abc ===Les accolades (le caractère précédent un nombre exact de fois) : === grep -E "1A{3}\.A{3}\..*" liste4-spec 7 1AAA.AAA.bcdef aBcd6a 123* ===Le caractère précédent au moins "n" fois :=== grep -E "[0-9]{4,}" liste4-spec abc2356.99 73000|Savoie -15 +36 5687 {15} exemple{36} 123.3456.abc ===Le caractère + et parenthèses === grep -E "(1A{3}\.)+.*" liste4-spec 7 1AAA.AAA.bcdef aBcd6a 123* ===Le caractère ? === grep -E "trucs?" liste4-spec il y a un truc et un truc et encore un truc et une chose choses et trucs ne font pas bon ménage trucschosetruc tructructrucs >On cherche les lignes qui comporte "truc" au singulier ou au pluriel. ===Le caractère d'alternative | === grep -E "(truc|chose)" liste4-spec il y a un truc et un truc et encore un truc et une chose choses et trucs ne font pas bon ménage trucschosetruc tructructrucs chosechosechose ====sed et les caractères spécifiques aux ERe ==== __**Rappel**__\\ Par défaut sed utilise les ERb.\\ Pour s'éviter de mettre un antislash devant parenthèse, accolade, ?, +, |,\\ il faut utiliser **l'option -r**.\\ Sans option et avec l'antislash le signification de ces caractères sont les mêmes que lors de leur utilisation avec l'option -r. ===Exemples === * __Substituer "Hello" par "OK" :__ echo "coucou Hello Yep" | sed -r 's/[A-Z]{1}[a-z]{4}/OK/g' coucou OK Yep * __Substituer "a" et "aa" par "OK" :__ echo "a aa aaa aaaa aaaaaa aaaaaaaa" | sed -re 's/(a{1} )/OK/'\ -e 's/(a{2} )/OK/' OKOKaaa aaaa aaaaaa aaaaaaaa L'antislash de la commande précédente permet de couper les longues commandes.\\ Ne pas confondre avec l'antislash utiliser pour les ERb et les caractères spécifiques, parenthèses, accolades, etc. ====find et les caractères spécifiques==== __**Rappel **__\\ Pour utiliser les ERe, il faut utiliser l'option **''-regextype "posix-extended" ''**.\\ Pour les caractères **'' [ ] { } ? + ''**, on peut là aussi choisir les ERb en mettant un antislash devant.\\ Pour ce faire, il faut alors utiliser l'option **''-regextype "posix-basic" ''**. __**Préparation**__\\ Rappel : le répertoire "ERetCMD/" contient : Dossier img-perso-2.jpg liste2-nom server-0.xkb image linux - 01.jpg liste liste3-erb-ere smolski-exo-sed.txt image linux - 02.jpg liste1 liste4-spec sort1.txt image linux - 03.jpg liste1-nom liste4-vim sort2.txt img-perso-1.jpg liste2 liste-class sort3.txt ===Exemples === * __Les accolades__ (depuis le répertoire parent "ERetCMD/" des fichiers recherchés : find -regextype "posix-basic" -regex ".*/[a-z]\{,3\}-.*\.jpg$" ./img-perso-2.jpg ./img-perso-1.jpg ou find -regextype "posix-extended" -regex ".*[a-z]{,3}-.*\.jpg$" ./img-perso-2.jpg ./img-perso-1.jpg * __Le caractère ? :__ find -regextype "posix-basic" -regex ".*/liste.\?" ./ERetCMD/liste1 ./ERetCMD/liste ./ERetCMD/liste2 * __Le caractère +__ (depuis le répertoire parent "ERetCMD/" des fichiers) : find -regextype "posix-extended" -regex ".*liste.+" ./liste2-nom ./liste1-nom ./liste3-erb-ere ./liste4-vim ./liste1 ./liste4-spec ./liste2 ./liste-class ====locate et les caractères spécifiques==== __**Rappel**__\\ Pour utiliser les ERe, il faut utiliser l'option **''--regex''**.\\ De même que précédemment, on peut choisir l'option **''--regexp''** pour utiliser les caractères spécifiques aux ERb qui nécessitent **''\''**. Soit encore le répertoire "ERetCMD/" contenant les mêmes fichiers.\\ Mise à jour de la base de donnée, si besoin : updatedb ===Exemples === * __Parenthèses et accolades__ (depuis n'importe où dans l'arborescence du système de fichiers) : locate --regexp '\([a-z]\{1,\} \)\{2\}.*\.jpg$' /home/Téléchargements/Les utilitaires awk, nawk et gawk - Tutoriel_fichiers/logo.jpg /home/hypathie/ERetCMD/image linux - 01.jpg /home/hypathie/ERetCMD/image linux - 02.jpg /home/hypathie/ERetCMD/image linux - 03.jpg > D'autres fichiers que ceux du répertoire "~/ERetCMD/" et créés pour les exemples peuvent apparaître. ou locate --regex '([a-z]{1,} ){2}.*\.jpg$' /home/Téléchargements/Les utilitaires awk, nawk et gawk - Tutoriel_fichiers/logo.jpg /home/hypathie/ERetCMD/image linux - 01.jpg /home/hypathie/ERetCMD/image linux - 02.jpg /home/hypathie/ERetCMD/image linux - 03.jpg * __Caractère ? :__ locate --regex '/liste.?' /home/hypathie/Documents/PYTHON/python2/chap06/liste_et_branch.py /home/hypathie/Documents/PYTHON/python3/chap06/liste_et_branch.py /home/hypathie/ERetCMD/liste /home/hypathie/ERetCMD/liste-class /home/hypathie/ERetCMD/liste1 /home/hypathie/ERetCMD/liste1-nom /home/hypathie/ERetCMD/liste2 /home/hypathie/ERetCMD/liste2-nom /home/hypathie/ERetCMD/liste3-erb-ere /home/hypathie/ERetCMD/liste4-spec /home/hypathie/ERetCMD/liste4-vim /usr/share/man/man2/listen.2.gz >Le fichier "liste" (sans extension) apparaît. * __Caractère + :__ locate --regex '/liste.+' /home/hypathie/Documents/PYTHON/python2/chap06/liste_et_branch.py /home/hypathie/Documents/PYTHON/python3/chap06/liste_et_branch.py /home/hypathie/ERetCMD/liste-class /home/hypathie/ERetCMD/liste1 /home/hypathie/ERetCMD/liste1-nom /home/hypathie/ERetCMD/liste2 /home/hypathie/ERetCMD/liste2-nom /home/hypathie/ERetCMD/liste3-erb-ere /home/hypathie/ERetCMD/liste4-spec /home/hypathie/ERetCMD/liste4-vim /usr/share/man/man2/listen.2.gz >Le fichier "liste" (sans extension) n'apparaît plus. =====Les classes ===== ====symboles et significations ==== ^ ^ ^ |''[[:alnum:]]'' | Alpha-numerique [a-z A-Z 0-9]| |''[[:alpha:]]'' | Alphabetic [a-z A-Z] | |''[[:blank:]]'' | Espaces ou tabulations | |''[[:cntrl:]]'' | Caractères de contrôle | |''[[:digit:]]'' | Nombres [0-9] | |''[[:graph:]]'' | Tous les caractères visibles (à l'exclusion des espaces)| |''[[:lower:]]'' | Lettres minuscules [a-z] | |''[[:print:]]'' | Caractères imprimables (tous caractères sauf ceux de contrôle)| |'' [[:punct:]] '' | Les caractères de ponctuation | |''[[:space:]]'' | Les espaces | |''[[:upper:]]'' | Les lettres majuscules [A-Z] | |''[[:xdigit:]]'' | Chiffres hexadécimaux [0-9 a-f A-F] | ====grep, grep -E et les classes==== La commande grep utilise les classes soit comme ERb et soit comme ERe, c'est-à-dire sans l'option -E ou avec l'option -E ===Préparation === * soit le fichier " cd ~/ERetCMD/ && cat >> liste-class < ===[[:class:]] + quantificateur { }=== grep "[[:digit:]]\{4\}" liste-class abc2356.99 73000|Savoie 123456 1234567 -15 +36 5687 {15} exemple{36} 123.3456.abc >Sélection de "3456" ; "5687" ; de "2356" ; et des lignes avec plus de 4 chiffres consécutif. grep "[[:digit:]]\{6\}" liste-class 123456 1234567 > Sélectionne les lignes comportant 6 chiffres consécutifs et de 7 chiffres. > grep sélectionne les lignes lorsqu'il trouve exactement 4 chiffres sans se préoccuper de ce qu'il y a après, même s'il y a d'autres chiffres. En réalité, c'est à nous de préciser avec la ER qu'il faut tenir compte de ce qu'il y a après cet "exactement 6 chiffres". >Les classes servent à décrire des sous-chaînes ou des lignes entières plus facilement et ne relèvent pas des expressions rationnelles dites "atomiques". * Il en va de même avec les ERe : grep -E "[[:digit:]]{6}" liste-class 123456 1234567 ===classes et sous-chaîne === * En tant que ERb : grep "\([[:digit:]]\{4\}\)[\. ]" liste-class abc2356.99 -15 +36 5687 {15} exemple{36} 123.3456.abc * En tant que ERe : grep -E "([[:digit:]]{4})[\. ]" liste-class abc2356.99 -15 +36 5687 {15} exemple{36} 123.3456.abc >Dans l'exemple ci-dessus, avec les ERe, on pourrait remplacer ''[\. ]'' par ''(\.| )'' ====locate et les classes, ERb ou ERe==== * Rappel du contenu de "~/ERetCMD/" : ls Dossier img-perso-2.jpg liste2-nom server-0.xkb image linux - 01.jpg liste liste3-erb-ere smolski-exo-sed.txt image linux - 02.jpg liste1 liste4-spec sort1.txt image linux - 03.jpg liste1-nom liste4-vim sort2.txt img-perso-1.jpg liste2 liste-class sort3.txt ===Sous-chaîne avec classes dans une ERb=== >Option --regexp et on met un antislash de toutes les parenthèses et les accolades. locate --regexp '.*\([[:lower:]]\{4,5\} \)\{2\}.*\.jpg$' /home/hypathie/ERetCMD/image linux - 01.jpg /home/hypathie/ERetCMD/image linux - 02.jpg /home/hypathie/ERetCMD/image linux - 03.jpg >D'autres fichiers créés avant l'exercice peuvent apparaître. ===Sous-chaîne avec classes dans une ERe=== >Idem mais avec option --regex et on enlève les ''\'' inutiles avec les ERe locate --regex '.*([[:lower:]]{4,5} ){2}.*\.jpg$' /home/hypathie/ERetCMD/image linux - 01.jpg /home/hypathie/ERetCMD/image linux - 02.jpg /home/hypathie/ERetCMD/image linux - 03.jpg ====find et les classes, ERb ou ERe ==== ===Les classes et ERb === option : -regextype "posix-basic" find -regextype "posix-basic" -regex ".*/[[:lower:]]\{,3\}-.*\.jpg$" ./img-perso-2.jpg ./img-perso-1.jpg ===Les classes et ERe === option : -regextype "posix-extended" et on enlève ''\'' devant accolades ou parenthèses find -regextype "posix-extended" -regex ".*/[[:lower:]]{,3}-.*\.jpg$" ./img-perso-2.jpg ./img-perso-1.jpg ===Pour sed les classes en tant que ERe=== Rappel :\\ sed utilise les ERb sans option et les ERe avec l'option -r, mais pour utiliser les classes, il faut utiliser l'option -r. *Exemple 1 : echo "123ab efab ef123" | sed -r 's/(ab[[:blank:]]ef){2}/OK/' 123OK123 * Exemple 2 : echo "a aa aaa " | sed -r 's/([[:alpha:]])/1/g' 1 11 111 >Il ne s'agit que de donner le détail des commandes quant à l'utilisation des //ER//. > Remarquons au passage la différence avec et sans le flags ''g'' qui applique "partout". >Et encore une fois l'effet d'une //ER// dépend de ce que fait la commande * Exemple 3 : echo "a aa aaa " | sed -r 's/(a{1}[[:alpha:]])/2/g' a 2 2a >Pour "protéger" le premier caractère "a", on substitue en "remettant" un "a" ! ===sed permet d'utiliser la mémorisation \n avec les classes=== * Exemple 1 : inversion de champs echo "abc 123" | sed -r 's/^([[:alpha:]]*) ([[:digit:]]*)/\2 \1/' 123 abc * Exemple : jusqu'à sous-chaîne n : echo "abc 123 hij" | sed -r 's/([[:alpha:]]*) ([[:digit:]]*) ([[:alpha:]]*)/x x \2/' x x 123 ====La commande expr utilise les classes en tant ERb==== * Exemple 1 : var=123 expr "$var" : '[[:digit:]]*$' 3 * Exemple 2 : extraire la première sous-chaîne : var="hypathie|00 rue Debian-facile|01011|ici" expr "$var" : '^[[:alpha:]]*|\([[:digit:]]*\).*\([[:digit:]]*\)$' 00 ====vi (vim) utilise les classes en tant que ERb==== ===Préparation === vim liste4-spec {{http://pix.toile-libre.org/upload/original/1408097498.png?400}} ===Exemples === * Recherche : /[[:alnum:]]\{7\}{[[:digit:]]\{2\}} {{http://pix.toile-libre.org/upload/original/1408097922.png?400}} * Substitution [[:graph:]]: :6,10s/[[:graph:]]/x/g {{http://pix.toile-libre.org/upload/original/1408098079.png?400}} > Les caractères accentués ne sont pas concernés car ils comportent un caractère de contrôle pour l'accentuation avec la touche morte. > Faire **'':nohlsearch''** et **''u''** pour la suite. * Substitution [[:print:]] : :6,10s/[[:print:]]/x/g {{http://pix.toile-libre.org/upload/original/1408098434.png?400}} > Cette fois les caractères accentués sont concernés s'ils font partie de l'adressage. > Faire **'':q!''** pour quitter sans enregistrer. =====awk les ERe et les classes===== cd ~/ERetCMD && cat >> liste2-nom < * Exemple 1, sélection de ligne avec ER comme condition : awk '/S[[:lower:]]*/' liste2-nom Samuel 27-08-2008 *Exemple 2, correspondance entre variable (champ n°2) et une ER : awk '$2 ~ /([[:digit:]]{2}-){2}2005$/' liste2-nom Hélène-Fleur 06-03-2005 =====Séquences d'échappement et programmes d'édition===== Sur les séquences d'échappement POSIX\\ voir : [[http://fr.wikipedia.org/wiki/Expression_rationnelle#S.C3.A9quences_d.E2.80.99.C3.A9chappement_POSIX]]\\ À ne pas confondre avec les classes abrégées supportées uniquement par les regex PCRE\\ voir : [[http://en.wikipedia.org/wiki/Regular_expression#Examples]] ====sed ==== ^Séquences ^Séquences ^ |**''\f''** | Produit ou correspond à un saut | |**''\n''** | Produit ou correspond à un retour à la ligne | |**''\t''** | Produit ou correspond à un onglet horizontal | |**''\v''** | Produit ou correspond à une tabulation verticale | |**''\w''** | Synonyme de **''[[:alnum:]]''** → correspond à un mot. | |**''\W''** | Synonyme de **''[^[:alnum]]''** → ce qui autre qu'un mot. | |**''\b''** | Correspond à une chaîne vide (blanc) à l'extrémité d'un mot | ====awk==== ^Séquences ^Séquences ^ |**''\b ''** | backspace (supprime le dernier caractère d'une chaîne) | |**''\f ''** | formfeed (nouvelle page) | |**''\r ''** | carriage return (retour à la ligne) | |**''\t ''** | tabulation (crée une tabulation de dix espaces) | |**''\c ''** | tout caractère pris sous sa forme littérale\\ excepté **''\''** |