Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
projets:ecole:scripting:initiation_au_shell [Le 06/04/2007, 11:10]
theytaz
projets:ecole:scripting:initiation_au_shell [Le 04/08/2023, 00:00] (Version actuelle)
Amiralgaby correction formatage des chevrons double pour ne pas être interprété par dokuwiki
Ligne 1: Ligne 1:
-Article mis en forme par ptitdav69 suite à la séance de formation qui a eu lieue le 27/01/2007 et qui a été dispensée par [[utilisateurs:​gapz]] et FiFouille sur le canal #ubuntu-fr-classroom du réseau IRC freenode.+{{tag>​script shell brouillon programmation }} 
 +---- 
 +====== Initiation au Shell ======
  
-====== Initiation à l'​utilisation du Shell ====== 
-===== Introduction ===== 
-Le sujet de ce cours est l'​initiation à l'​utilisation du Shell. Ce cours est orienté débutant et il devrait donc servir à construire des bases solides pour pouvoir ensuite apprendre plus facilement. 
-Les prérequis pour ce cours sont de savoir ouvrir un terminal, et d'​avoir un minimum de vocabulaire (pas grand chose rassurez vous). Pour ceux qui ont déja quelques notions, sachez que ce cours ne présentera pas quelques aspects du Shell et seront abordés dans une prochaine session. 
  
-==== Structure ​du cours ==== +Ceci est un compte-rendu ​du cours donné ​par gapz et FiFouille ​sur le canal IRC #​ubuntu-fr-classroom le 27 janvier 2007. Ce cours est orienté débutant ​et a pour but de donner de solides bases. Pour le suivre il suffit ​de savoir ouvrir un terminal.
-Le cours sera structuré de la façon suivante : en premier lieu le Shell dans sa généralité,​ puis des notions fondamentales telles que les entrées/​sorties,​ les pipes, les expressions régulières (présentées ​par FiFouilleet enfin les variables et les structures ​de contrôles.+
  
-===== Pourquoi s'​initier à l'​utilisation du Shell ? =====  +-----------------
-Le Shell vous donne accès à toute une gamme d'​outils très performants qui vous permettront d'​effectuer des tâches que vous n'​auriez pu faire auparavant, mais aussi de les automatiser,​ et cela d'une manière assez simple. +
-Bien que de nombreuses interfaces graphiques soient disponibles pour GNU/Linux (et autres dérivés d'​Unix),​ le shell reste un très bon outil car léger (donc assez rapide), efficace, accessible... +
-Bien sûr il y a beaucoup d'​autres aspects très importants, mais plus spécifiques aux langages, et qui donc demandent certaines connaissances en programmation,​ c'est pour cela que ces aspects ne seront pas traités ici (mais certainement dans une prochaine session).+
  
-===== Qu'​est-ce que le Shell ? ===== +===== Généralités ​=====
-C'est (dans une généralité),​ une interface entre l'​utilisateur et le système d'​exploitation. L'​utilisateur rentrera des commandes, qui ensuite seront interprétées par le Shell, et celui ci retournera un certain résultat. +
-Pour éviter toute confusion, nous allons apprendre quelques termes : quand on parle du Shell on fait souvent référence à l'​interpréteur de commande, auparavant celui-ci s'​appelait sh (contraction de shell), et qui à donné ensuite à tout un éventail d'​interpréteur tel que bash, csh, zsh, ksh... À ne pas confondre avec un émulateur de terminal comme xterm, eterm, gnome-terminal...+
  
-===== Comment utiliser ​le Shell ? ===== +Le **Shell** est une interface entre l'​utilisateur et le système d'​exploitationL'​utilisateur entre des commandes, ​qui sont ensuite interprétées par le Shellet celui-ci renvoie un certain résultat.
-Il vous faut un émulateur de terminal (gnome-terminal sous gnome, xterm, aterm...), pour pouvoir taper les commandes. Sachez que toutes les commandes peuvent être regroupées dans un fichier pour former un scriptnous aborderons cela un peu plus loin dans le cours. Pour le momentla plupart des exemples seront directement à taper dans le terminal.+
  
-Note sur la différence entre l'émulateur ​de terminal ​et tty : +{{icons:​iconnote.png ​ }} 
-Un émulateur de terminal est en quelque sorte l'outil graphique qui vous permet d'​avoir accès ​à votre Shell. +>Quand on parle du Shell, on fait souvent référence à l'interpréteur ​de commande, autrefois nommé sh (contraction de shell), ​et qui a ensuite donné naissance à tout un éventail d'​interpréteurs tels que bash, csh, zsh, ksh... qu'il ne faut pas confondre avec un émulateur de terminal ​comme xterm, eterm, gnome-terminal qui est un outil graphique qui permet d'​avoir accès ​au shell.
-En réalité, les vrais terminaux sont accessibles via la combinaison de touche CTRL + ALT + Fx (ou x est un chiffre entre 1 et 7, 7 étant la session graphique). +
-Le tty (pour TéléTYpe),​ c'est le "​terminal en mode caractère"​.+
  
-===== Les notions fondamentales ===== +En réalitéles vrais terminaux sont accessibles via la combinaison ​de touche CTRL + ALT + Fx (où x est un chiffre entre 1 et 6lorsque ​vous êtes dans un environnement graphique, le 7 correspondant à cette session. Si vous êtes dans un vrai Terminalil faut théoriquement utiliser ALT + FxÀ noter également qu'un émulateur permet d'​afficher une sorte de TTY (TéléTYpe) dans la session graphique.
-==== 1 - Les entrées/​sorties ==== +
-En général un programme dispose d'une entrée standardune sortie standard, et une sortie d'​erreur standard, aussi connu sous le nom de //stdin//, //stdout//, //stderr//. Globalement //stdin// représente le clavier, //stdout// l'​écran et //stderr// la sortie des messages d'​erreur vers l'​écran. Bien entendu ce n'est pas exactement cela, c'est simplement pour illustrer. +
-Pour "​simplifier",​ ils sont chacuns associés à un numéro (appelé descripteur de fichier: stdin **0**, stdout **1**, stderr **2**, cela permettera ensuite de faire ce que l'on appelle des redirections. +
-Par exemple, si vous avez un programme qui est lancé et qu'il est censé faire l'​addition de 1+1, le résultat sera retourné sur la sortie standard, et si jamais il y a une quelconque erreur elle sera retournée sur la sortie d'​erreur standard. +
-Si par exemple ​vous tapez "​lfdfdfj" ​dans le terminal"bash: lfdfdfj: command not found" sera retourné sur //stderr//Par contre, si vous tapez //ls//, le résultat sera retourné sur //stdout//. Pour l'utilisateur cela se passe de manière totalement transparente.+
  
 +Le Shell vous donne accès à toute une gamme d'​outils très performants qui permettent d'​effectuer des tâches impossibles jusque là mais aussi de les automatiser,​ et cela d'une manière assez simple. De nombreuses interfaces graphiques sont certes disponibles,​ mais le shell reste très léger, rapide, accessible, efficace...
  
-==== 2 Les redirections ==== +-----------------
-Les redirections permettent simplement (comme le nom l'​indique),​ de rediriger un des trois descripteurs de fichier vu plus haut vers à peu près tout ce que vous voulez (c'est à dire dans un fichier). Les opérateurs utilisés sont ">",​ ">>",​ "<",​ "<<"​.+
  
-=== Redirections "​sortie" ​=== +===== Entrées / Sorties =====
-Si vous souhaitez rediriger le résultat de //ls// dans un fichier portant le nom de test il vous suffira de faire : "ls > test". Si vous voulez rediriger la //stderr// de la commande "​lfdfdfj"​ il faudra faire : "ls 2> test".+
  
-Comme vous l'aurez sans doute remarqué dans le premier exempleon n'indique pas explicitement "​1>"​ car par défaut ​le descripteur ​de fichier redirigé est //stdout// (dans le cas de l'opérateur ">"​). +En général, un programme dispose d'une **entrée standard**d'une **sortie standard**, et d'une **sortie d'​erreur standard**, aussi connues sous le nom de **stdin**, **stdout**, **stderr**. Globalement stdin représente ​le clavier, stdout ​l'écran et stderr la sortie des messages d'​erreur ​vers l'​écran : ceci peut bien entendu varier suivant les programmes, il ne s'agit que d'un exemple.
-Quand vous utiliserez ">"​ le contenu du fichier ​vers lequel //stdout// est redirigé sera écraséet si le fichier n'​existe pas il sera créé. +
-C'est pour cela qu'existe ">>",​ qui permet de rediriger //stdout// dans le fichier spécifié mais sans en écraser son contenu. Par exemple ​: "ls >> test", si test n'​existe pas il sera créé, si il existe le résultat sera ajouté à son contenu. De la même manière vous pouvez donc rediriger //stderr// : "​lfdfdfj 2>> test".+
  
-Cela ne s'​arrête pas là, si par exemple vous voulez rediriger ​//stderr// vers //stdout//, il vous suffit alors d'​utilisez "​2>&​1"​ qui signifie littéralement rediriger //stderr// vers ce que représente //​stdout//​. +À chaque entrée/sortie est associée un numéro appelé **descripteur de fichier** comme vous pouvez le voir dans ce tableau récapitulatif :
-Par exemple "ls >fichier ​2>&​1"​ redirigera //stdout// dans fichier ainsi que //stderr//. Si vous rencontrez "&>​fichier"​ cela signifie rediriger //stdout// et //​stderr// ​dans fichier.+
  
-=== Redirection vers l'​entrée ​standard ​=== +^ Entrées/​Sorties ​            ^ Nom      ^ Numéro ​  ^ 
-Les opérateurs utilisés sont "<"​ et "<<"​ qui permettent tout les deux de rediriger l'​entrée ​standard. +| Entrée ​standard ​            |  stdin   ​| ​  ​0 ​     | 
-Si l'on utilise le programme wc (qui permet ​d'afficher le nombre d'​octets,​ de mots et de lignes d'un fichier, cf. man wc), on peut rediriger //stdin// via "<"​. Par exemple si l'on veut compter le nombre de ligne dans un fichier : "wc -l < fichier"​ (revient aussi à faire "wc -l fichier",​ mais cela est du au fait que wc -l peut prendre en paramètre un nom de fichier). ​+| Sortie ​standard ​            |  stdout ​ |   ​1 ​     | 
 +| Sortie ​d'erreur standard ​   |  stderr ​ |   ​2 ​     |
  
-"<<"​ quand à lui permet aussi de rediriger //stdin// mais jusqu'à arriver à une chaine ​de caractère que l'on aura spécifiéeExemple : "wc -l << EOF" (EOF signifiant End Of Filevous pouvez utiliser de la même manière "​FIN"​ou encore "​FDF"​ etc...). +Par exemple, prenons un programme censé effectuer l'addition ​de 1 et de 1Une fois lancéce programme donnera un résultat dans la sortie standard alors que s'il y a une erreurelle nous parviendra via la sortie d'erreur ​standard.
-En utilisant ">"​ et "<<" ​nous pouvons facilement ajouter du texte dans un fichier de notre choix de la même manière qu'un éditeur de texte : "cat > fichier << EOF" (l'​outil cat permet de concaténer des fichiers et les afficher sur la sortie ​standard).+
  
-=== null - un fichier spécial === +Concrètement si vous exécutez "​lfdfdfj"​ dans un terminal"bash: lfdfdfj: command not found" sera retourné sur stderrPar contresi vous tapez ls, le résultat ​sera retourné sur stdout.
-Même si cela ne traite pas directement des redirectionsil est important de connaitre un fichier spécial nommé **null**Il permet de rediriger un descripteur de fichier vers un fichier qui supprimera toutes les données qui lui seront ajoutées. Il porte le nom d'​absorbeur de données. Si par exemple, vous ne voulez pas voir le résultat ​d'une commande, il vous suffit de rediriger //stdout// vers /dev/null : "ls >/​dev/​null"​. Pour plus d'​information sur le fichier null, "man null".+
  
-==== 3 Les commandes de bases pour traiter les fichiers ==== +-----------------
-Comme cela n'est pas le but du cours, cette partie sera assez rapide, mais vous pouvez à tout moment, si vous ne saisissez pas quelques consulter le manuel via la commande "man nom_du_programme"​ (par exemple "man ls"​). +
-L'​interêt de cette partie est de vous fournir une gamme d'​outil permettant ensuite de présenter des notions concernant directement le shell. +
-Les commandes les plus courament utilisées sont donc : cp, mv, ls, cd, rm, chmod, chown, find +
-Chacune de ces commandes correspondent à directement à un mot. Parexemple cp = **c**o**p**y,​ mv = **m**o**v**e,​ ls = **l**i**s**t,​ cd = **c**hange **d**irectory+
  
-**REMISE EN FORME EN COURS**+===== Redirections ===== 
 + 
 +Les **redirections** permettent simplement (comme leur nom l'​indique),​ de rediriger un des trois descripteurs de fichier vu plus haut vers à peu près tout ce que vous voulez. Les opérateurs utilisés sont ">",​ %%">>"​%%,​ "<"​ et %%"<<"​%% 
 + 
 +==== Sorties ==== 
 + 
 +Prenons un exemple, on connaît la commande "​ls"​ qui donne la liste des fichiers d'un répertoire et on veut enregistrer le résultat dans un fichier. Pour cela on    va rediriger le résultat dela sortie standard dans le fichier test à l'aide de la commande suivante : 
 + 
 +<​code>​ls > test</​code>​ 
 + 
 +De même si on veut enregistrer stderr de la commande "​lfdfdfj",​ on utilise : 
 + 
 +<​code>​lfdfdfj 2> test</​code>​ 
 + 
 +Dans le premier exemple, on peut constater que l'on ne précise pas le descripteur de fichier redirigé (1), en effet le descripteur de fichier redirigé par défaut est stdout. 
 + 
 +Techniquement,​ lorsque ">"​ est utilisé le fichier vers lequel la sortie est redirigée est créé s'il n'​existait pas auparavant, sinon il est écrasé. 
 + 
 +Pour conserver le fichier original, vous pouvez utiliser %%">>"​%% qui n'​écrasera pas le contenu du fichier s'il existe déjà. Par exemple : 
 + 
 +<​code>​ls >> test</​code>​ 
 + 
 +Si test n'​existe pas il sera créé, si il existe le résultat sera ajouté à son contenu (à la fin du fichier). De la même manière, vous pouvez rediriger stderr : 
 + 
 +<​code>​lfdfdfj 2>> test</​code>​ 
 + 
 +Mais il est également possible de rediriger une sortie vers une autre sortie, par exemple "​2>&​1"​ signifie "​rediriger stderr vers ce que représente stdout"​. Ainsi 
 + 
 +<​code>​ls > test 2>&​1</​code>​ 
 + 
 +redirigera stdout et stderr dans le fichier test. Vous remarquerez que les redirections s'​effectuent de droite à gauche : la sortie stderr 2 est tout d'​abord redirigée vers la sortie stdout 1, puis la sortie standard de ls s'​inscrit dans le fichier test. 
 + 
 +==== Entrées ==== 
 + 
 +Pour rediriger vers l'​entrée standard stdin, nous allons utiliser "<"​ et %%"<<"​%%. 
 + 
 +"​wc"​ permet de compter le nombre de lignes (option -l) ou de mots (option -w), plus d'​informations dans la page man de wc, en entrée. Pour compter le nombre de lignes d'un fichier on peut donc utiliser : 
 + 
 +<​code>​wc -l < fichier</​code>​ 
 + 
 +Cette commande donnera le même résultat car wc peut prendre un fichier comme paramètre : 
 +  
 +<​code>​wc -l fichier</​code>​ 
 + 
 +%%"<<"​%% permet lui aussi de rediriger stdin mais jusqu'​à une chaîne de caractère que l'on précisera : littéralement on pourrait dire que %%<<​%% transmet notre entrée standard (clavier) au programme à sa gauche, et cela jusqu'​à ce qu'il rencontre une ligne EOF ((End of File : Fin de fichier)). 
 + 
 +Par exemple la commande suivante vous permettra de taper un texte, d'​aller à la ligne autant de fois que vous voulez en appuyant sur Entrée, puis lorsque vous taperez EOF (pour End of File, fin du fichier) et entrée, elle comptera le nombre de lignes (celle de EOF non comprise) que vous avez entrées. 
 + 
 +<​code>​wc -l << EOF</​code>​ 
 + 
 +Vous pouvez bien sur spécifier un chaîne différente de EOF comme FIN, END... 
 + 
 +En utilisant %%">>"​%% et %%"<<"​%% nous pouvons facilement ajouter du texte dans un fichier de notre choix de la même manière qu'un éditeur de texte : 
 + 
 +<​code>​cat >> fichier << EOF</​code>​ 
 + 
 +Le texte tapé sera ajouté au fichier jusqu'​à ce que vous vous écriviez EOF et validiez par entrée. 
 + 
 +==== >/​dev/​null 2>&1 ==== 
 +Expliquons cette syntaxe très souvent rencontrée et reprise sans explication : <​code>​commande >/​dev/​null 2>&​1</​code>​ 
 +Dans l'​ordre,​ est exécuté : 
 + 
 +- commande (dont les stdout et stderr sont redirigées) 
 + 
 +- stdout vers /dev/null (le trou noir) 
 + 
 +- stderr vers stdout ... donc vers /dev/null 
 + 
 +La commande exécutée ne renverra ni sa sortie, ni ses messages d'​erreur. 
 +C'est équivalent à : <​code>​commande > /dev/null 2 > /​dev/​null</​code>​ 
 + 
 +{{icons:​iconnote.png ​ }} 
 +>Même si cela ne traite pas directement des redirections,​ il est important de connaitre un fichier spécial nommé **null**. Il permet de rediriger un descripteur de fichier vers un fichier qui supprimera toutes les données qui lui seront ajoutées. Il porte le nom d'​**absorbeur de données**. Si par exemple vous ne voulez pas voir le résultat d'une commande, il vous suffit de rediriger stdout vers /dev/null : "ls >/​dev/​null"​. Pour plus d'​information sur le fichier null voir la page man de null. 
 + 
 +----------------- 
 + 
 +===== Commandes de base pour traiter les fichiers ===== 
 + 
 +Si vous avez besoin de plus d'​informations sur une commande n'​hésitez pas à consulter son manuel via la commande : 
 + 
 +<​code>​man nom_du_programme</​code>​ 
 + 
 +Pour cette partie, consulter http://​doc.ubuntu-fr.org/​console/​commandes_de_base pour les commandes fondadamentales : cp, mv, ls, cd, rm, chmod, chown et find. 
 + 
 +==== Cut ==== 
 + 
 +Pour présenter l'​outil **cut** nous allons par exemple considérer que nous voulons obtenir le premier mot (correspondant au nom de l'​utilisateur) du fichier /​etc/​passwd. 
 + 
 +Avec cut, vous pouvez supprimer une partie de chaque ligne d'un fichier, soit en indiquant un séparateur (avec l'​option -d), soit en indiquant la position (via -c). 
 + 
 +Voyons tout de suite un exemple : 
 + 
 +<​code>​cut -d: -f1 /​etc/​passwd</​code>​ 
 + 
 +L'​option "​-d:"​ indique que le **séparateur** sera ":",​ et "​-f1"​ indique que l'on veut récupérer seulement la **première partie**. 
 + 
 +{{:​icons:​icontip.png ​ }} 
 +>Pour utiliser l'​espace comme caractère de séparation,​ utilisez l'​option -d" ". 
 + 
 +On peut aussi récupérer plusieurs parties en une seule fois en les séparant par des virgules, ici les parties 1 et 5 : 
 + 
 +<​code>​cut -d" " -f1,5 un_fichier</​code>​ 
 + 
 +Maintenant si l'on travaille en fonction de la position : 
 + 
 +<​code>​cut -c 1-10 /​etc/​passwd</​code>​ 
 + 
 +Vous l'​aurez compris cette commande récupère les caractères de 1 à 10 du fichier passwd. 
 + 
 +==== Head et Tail ==== 
 + 
 +Il est souvent utile de ne voir que le début ou que la fin d'un texte, du résultat d'une commande,​... Il existe pour cela deux outils : **head** (tête en français) et **tail** (queue en français). 
 + 
 +Par exemple, on désire afficher les 5 premières lignes du fichier /​var/​log/​Xorg.0.log : 
 + 
 +<​code>​head -n 5 /​var/​log/​Xorg.0.log</​code>​ 
 + 
 +Pour les 5 dernières : 
 + 
 +<​code>​tail -n 5 /​var/​log/​Xorg.0.log</​code>​ 
 + 
 +Pour récupérer le résultat d'une commande, nous allons utiliser l'​opérateur | appelé **pipe** (qui signifie tuyau...), son fonctionnement sera expliqué plus bas. Pour récupérer les 5 dernières du résultat dedmesg : 
 + 
 +<​code>​dmesg | tail -n 5</​code>​ 
 + 
 +L'​option -f permet d'​afficher,​ à chaque fois qu'ils ont lieu, les ajouts au fichier, par exemple : 
 + 
 +<​code>​tail -f /​var/​log/​syslog</​code>​ 
 + 
 +===== Les pipes ===== 
 + 
 +D'une manière générale les pipes sont tout une gamme d'​**opérateurs**. Par exemple les opérateurs de redirection sont des pipes. La plupart du temps lorsque l'on parle de pipe, on parle seulement de "​|"​. 
 + 
 +==== Présentation de "​|"​ ==== 
 + 
 +Cet opérateur permet d'​envoyer la **sortie standard** d'un programme **vers** **l'​entrée standard** d'un second programme, cela permet ainsi l'​enchaînement des commandes. Par exemple : 
 + 
 +<​code>​ls | wc -l</​code>​ 
 + 
 +La sortie standard de "​ls"​ devient l'​entrée standard de "wc -l". 
 + 
 +Autres exemples : 
 + 
 +<​code>​cat fichier | wc -l</​code>​ 
 + 
 +<​code>​ls -l | sort</​code>​ 
 + 
 +{{:​icons:​icontip.png ​ }} 
 +>sort permet de trier les lignes d'un fichier texte, pour plus d'​information "man sort"​. 
 + 
 +Vous pouvez bien sûr étendre cela à plus de deux programmes : 
 + 
 +<​code>​cat fichier | wc -l | wc -L</​code>​ 
 + 
 +Vous pouvez aussi utiliser les redirections vues précédemment : 
 + 
 +<​code>​ls -la > fichier | wc -l</​code>​ 
 + 
 +Dans le cas de "ls -la > fichier"​ nous pouvons remarquer qu'il n'y a rien sur stdout ou stderr. Pour pallier à cela le programme tee permet de copier l'​entrée standard sur la sortie standard et dans un fichier : "ls -la | tee fichier"​. 
 + 
 +Ainsi on utilisera : 
 + 
 +<​code>​ls -la | tee fichier | wc -l</​code>​ 
 + 
 +==== Présentation de "&"​ ==== 
 + 
 +Cet opérateur permet de lancer simultanément deux commandes dont la première sera lancée en arrière plan. Par exemple : 
 + 
 +<​code>​ls & ls -la</​code>​ 
 + 
 +{{icons:​iconnote.png ​ }} 
 +Vous pouvez aussi l'​utiliser pour mettre un programme en arrière plan : "ed &"​. Pour reprendre la main sur ce programme il faut utiliser la commande fg. 
 + 
 + 
 +==== Présentation de "&&"​ ==== 
 + 
 +Pour pouvoir bien comprendre ce que fait cet opérateur il faut d'​abord parler rapidement des **codes de retour** : quand vous lancez une commande, si elle se termine correctement alors le code de retour est "​0",​ ce qui correspond à un succès, dans le cas contraire le code de retour est différent de 0 (bien entendu les codes de retour différents de 0 ont une signification qui ne sera pas expliquée ici). 
 + 
 +Si par exemple vous rentrez une commande erronée, le code de retour sera différent de 0 : "​fgsfdg"​. 
 + 
 +Pour voir le code de retour de la dernière commande lancée : 
 + 
 +<​code>​echo $?</​code>​ 
 + 
 +L'​opérateur "&&"​ permet de lancer une commande si et seulement si la première (celle à gauche de l'​opérateur) s'est correctement terminée : 
 + 
 +<​code>​ls && ls /</​code>​ 
 + 
 +Si la commande "​ls"​ se termine correctement alors "ls /" sera exécutée. Un second exemple : 
 + 
 +<​code>​fdgfdsg && ls</​code>​ 
 + 
 +==== Présentation de "​||"​ ==== 
 + 
 +C'est simplement l'​inverse de "&&"​. La commande à droite de l'​opérateur est exécutée seulement si le code de retour de la première commande est différent de 0 (donc s'il y a eu une erreur) : 
 + 
 +<​code>​fhgfdsjk || ls</​code>​ 
 + 
 +Dans ce cas "​ls"​ sera exécuté. 
 + 
 +==== Présentation de ";"​ ==== 
 + 
 +Cet opérateur est équivalent à un retour à la ligne, c'est à dire que "ls; ls -l" exécutera "​ls"​ dans un premier temps puis, une fois la première commande finie et quel que soit son code de retour, "ls -l" sera exécuté. 
 + 
 +-------------------------------- 
 + 
 + 
 +===== Les expressions régulières ===== 
 + 
 +Les **expressions rationnelles**,​ souvent appelées **expressions régulières**,​ **regex** ou **regular expressions** sont des notations qui permettent de décrire des chaînes de caractères,​ d'en reconnaître,​ d'en manipuler. 
 + 
 +Pour commencer nous allons chercher grâce à elles des mots dans le dictionnaire /​usr/​share/​dict/​french,​ malheureusement celui-ci a des problèmes d'​accents,​ on va donc le convertir en un fichier où l'on pourra lire les accents : 
 + 
 +<​code>​iconv -f ISO-8859-15 -t UTF-8 /​usr/​share/​dict/​french > /​tmp/​french.utf8</​code>​ 
 + 
 +Pour plus d'​informations sur iconv, voir la page du manuel. Maintenant notre dictionnaire est /​tmp/​french.utf8 . 
 + 
 +Nous allons chercher les mots qui finissent par -er, pour cela on parcourt le fichier avec grep et on ne sort que les lignes finissant par -er : 
 + 
 +<​code>​grep '​er$'​ /​tmp/​french.utf8</​code>​ 
 + 
 +L'​opérateur **$** indique donc la **fin de ligne**. 
 + 
 +Maintenant on désire chercher les mots commençant par absol- : 
 + 
 +<​code>​grep '​^absol'​ /​tmp/​french.utf8</​code>​ 
 + 
 +L'​opérateur **^** indique le **début d'une ligne**. 
 + 
 +On cherche maintenant les mots de 4 caractères commençant et finissant par un t, pour cela on utilise l'​opérateur "​**.**"​ qui remplace n'​importe quel caractère, il est parfois appelé **wildcard** : 
 + 
 +<​code>​grep '​^t..t$'​ /​tmp/​french.utf8</​code>​ 
 + 
 +Pour avoir exactement la ligne contenant "​coucou",​ qui doit donc commencer et finir par coucou : 
 + 
 +<​code>​grep '​^coucou$'​ /​tmp/​french.utf8</​code>​ 
 + 
 +==== Les modificateurs ==== 
 + 
 +  * * représente **0 ou plus** caractères. Exemple : d* = 0 ou plus fois "​d"​. 
 +  * + représente **1 ou plus** caractères. 
 +  * ? représente **0 ou 1** caractère. 
 + 
 +Par exemple si l'on cherche les mots commençant par "​t"​ et finissant par "​tant"​ : 
 + 
 +<​code>​grep '​^t.*tant$'​ /​tmp/​french.utf8</​code>​ 
 + 
 +"​^t"​ nous donne les mots commençant par "​t",​ "​tant$"​ prends ceux finissant par "​tant"​ et au milieu on veut 0 ou plus fois n'​importe quel caractère, donc le "​."​. 
 + 
 +On veut maintenant chercher les mots contenant "​m"​ ou "​mm",​ pour cela on va utiliser une expression régulière étendue, il faudra donc utiliser l'​option "​-E"​ de grep : 
 + 
 +<​code>​grep -E '​m{1,​2}'​ /​tmp/​french.utf8</​code>​ 
 + 
 +Remarque : cette expression donne les mots contenant 1 ou 2 m consécutifs ou non. 
 + 
 +{{:​icons:​icontip.png ​ }} 
 +>Les expressions régulières étendues se calculent moins rapidement que celles de bases, pour alléger les programmes elles sont regroupées et accessibles via -E. 
 + 
 +Pour être toujours plus fou, on veut maintenant trouver tous les noms finissant par "​eux"​ ou "​eut"​ pour créer des noms de domaines en "​.eu"​. Pour cela on prend les mots qui commencent par n'​importe quoi grâce à "​^.*",​ puis qui terminent par "​x"​ ou "​t"​ grâce à "​[xt]",​ tout ça avec "​eu"​ au milieu bien sûr : 
 + 
 +<​code>​grep '​^.*eu[xt]$'​ /​tmp/​french.utf8</​code>​ 
 + 
 +On peut ainsi chercher les jeux pour KDE et pour GNOME, en supposant que tout jeu pour KDE qui se respecte commence par un "​k"​ et par "​g"​ pour GNOME. Pour cela on cherche tous les jeux, et on ne garde que ceux qui commencent par "​k"​ ou "​g"​ : 
 + 
 +<​code>​apt-cache search games | grep '​^[gk]'</​code>​ 
 + 
 +Maintenant on veut chercher les jeux qui ne commencent ni par "​g"​ ni par "​k"​ : 
 + 
 +<​code>​apt-cache search games | grep '​^[^gk].*'​ | grep -v '​^lib'</​code>​ 
 + 
 +Comme on l'a déjà vu [^gk] retourne ce qui commence par un "​g"​ ou un "​k",​ le "​^"​ devant l'​expression **[]** joue le rôle de **négation** : on prends ceux qui ne commencent ni par "​g"​ ni par "​k"​. Puis grâce à "​.*"​ on accepte n'​importe quelle fin. Mais cette requête renvoie beaucoup trop de résultats, on effectue donc un deuxième filtrage en éliminant ceux qui commencent par "​lib"​ grâce à l'​option -v de grep qui enlève les lignes correspondant à la condition. 
 + 
 +Autre exemple instructif : 
 + 
 +<​code>​ls / | grep -E '​^m(edia|root)'</​code>​ 
 + 
 +Les parenthèses permettent d'​isoler un regroupement,​ et le | correspond à "​où"​. Ceci renvoie donc les fichiers/​dossiers à la racine commençant par media ou mroot. 
 + 
 +Alors que : 
 + 
 +<​code>​ls / | grep -E '​^media|root'</​code>​ 
 + 
 +renvoie les fichiers/​dossiers commençant par media ou par root. 
 + 
 +==== Sed ==== 
 + 
 +L'​utilisation de cet outil se fait comme ceci : 
 +<​code>​echo "du texte" | sed '​s/​(qui)/​(parquoi)'</​code>​ 
 + 
 +Ex : Pour remplacer la premiere occurence : 
 + 
 +<​code>​echo "​jean.durand@gmail.com"​ | sed 's/@/ at /' | sed 's/\./ pOiNt /'</​code>​ 
 + 
 +renvoie : 
 + 
 +<​code>​jean pOiNt durand at gmail.com</​code>​ 
 + 
 +On remplace le "​."​ par " pOiNt " et le "​@"​ par " at ", on voit ici que l'on a mis "​\"​ devant le "​.",​ le "​\"​ est le caractère d'​échappement : le "​."​ est alors considéré comme le caractère "​."​. 
 + 
 +De même si on veut remplacer "/"​ par "​slash",​ on utiliserait 
 + 
 +<​code>​s/​\//​ slash /</​code>​ 
 + 
 +On peut faire la même chose en moins long en utilisant l'​autre version de sed: 
 + 
 +<​code>​echo "​jean.durand@gmail.com"​ | sed -e 's/@/ at /' -e 's/\./ pOiNt /'</​code>​ 
 + 
 +Pour toute les occurrences ,on peut aussi utiliser : 
 +<​code>​s///​g</​code>​  
 +oû : 
 +<​code>​echo "​jean.durand@gmail.com"​ | sed -e 's/@/ at /' -e 's/\./ pOiNt /​g'</​code>​ 
 +qui donnera : 
 +<​code>​jean pOINT durand at gmail pOINT com</​code>​ 
 + 
 +On peut de même l'​appliquer sur des fichiers : 
 + 
 +<​code>​sed '​s/​kikoo/#​kikoolol/​g'​ /​etc/​config.txt</​code>​ 
 + 
 +Ceci remplace toute occurrence de "​kikoo"​ par "#​kikoolol"​ dans le fichier /​etc/​config.txt mais ne le modifie pas, le résultat est donné sur la sortie standard. Pour modifier le fichier il faut ajouter l'​option -i à sed. 
 + 
 +On peut enfin spécifier l’occurrence à remplacer : 
 + 
 +<​code>​echo "​moimoimoi"​ | sed '​s/​moi/​toi/​3'</​code>​ 
 + 
 +Donne : 
 + 
 +<​code>​moimoitoi</​code>​ 
 + 
 +<note warning>​l'​action de l'​option /n (n=1,​2,​3...) et /g sur un fichier n'est pas identique 
 +en effet 
 +si /g modifie bien toutes les occurrences du fichier 
 +/n ne modifie que la première ligne du fichier 
 +c'est pas clair : un exemple 
 + 
 +le fichier1 contient 3 lignes identiques kikoo 
 + 
 +le fichier2 contient kikookikookikoo et 2 lignes kikoo 
 + 
 +résultat de 
 +sed -i '​s/​kikoo/#​kikoo/​2 : 
 + 
 +le fichier1 n'est pas modifié ! 
 +  
 +le fichier 2 devient kikoo#​kikookikoo les 2 autres lignes ne sont pas modifiées 
 + 
 +---------------------------------------------------------- 
 +résultat de 
 +sed -i '​s/​kikoo/#​kikoo/​g ​ : les deux fichiers sont modifiés 
 + 
 +tous les kikoo deviennent #kikoo 
 + 
 +---------------------------------------------------------- 
 +</​note>​ 
 + 
 +Nous allons maintenant voir l'​utilisation de variables avec sed ce qui permet d'​échanger,​ de déplacer des parties d'une chaîne de caractères. Exemple : 
 + 
 +<​code>​echo "​jean.durand" ​ | sed -r '​s/​(.*)\.(.*)/​\2.\1/'</​code>​ 
 + 
 +(.*) représente l'​affectation des variables et \n la n-ième variable, ici on met donc ce qu'il y a avant le point ("​\."​) dans \1 et ce qu'il y a après dans \2 puis on met \2 devant \1, on obtient : 
 + 
 +<​code>​durand.jean</​code>​ 
 + 
 +Pour terminer nous allons voir un exemple pratique : nous avons de nombreux dossiers contenant de nombreux mp3 nommés selon le schéma Knoklezout_au_taquet-Jamendo-David_TMX.mp3 et on désire avoir le nom d'​artiste avant le titre de la chanson tout en enlevant la publicité pour Jamendo. 
 + 
 +Pour cela nous allons utiliser **rename** (qui vient avec perl) et nos chères expressions régulières : 
 + 
 +<​code>​rename '​s/​^(.*)-Jamendo-(.*)\.mp3/​$2_-_$1.mp3/'​ *.mp3</​code>​ 
 + 
 +Le principe est le même qu'​avec sed sauf que les variables sont notées $n et non plus \n : on met ce qu'il y a avant "​-Jamendo-"​ dans $1 et ce qu'il y a après ("​.mp3"​ non compris) dans $2 puis on formate comme on le veut. 
 + 
 +**rename** renomme les fichiers dans le dossier courant, pour plus de sécurité on peut utiliser ** rename -n '​s/'​** qui nous affiche les changements sans les effectuer, puis les effectuer une fois que l'on est sûr. 
 + 
 +===== Liens ===== 
 + 
 +Une introduction à Perl et une introduction au regexp : 
 +http://​sylvain.lhullier.org/​publications/​perl.html (FR) 
 + 
 +Le livre de référence (édition 1) de Ruby avec une petite partie sur les regexp 
 +http://​rubycentral.com/​book/​language.html (EN) 
 + 
 +Une introduction rapide réalisée dans notre FSUG (merci à Krunch) : 
 +http://​www.fsugar.be/​docu/​regex/​regex.html (FR) 
 + 
 +Une approche plus théorique avec Python: 
 +http://​www.amk.ca/​python/​howto/​regex/​ (EN) 
 + 
 +{{icons:​iconnote.png ​ }} 
 +>Les expressions régulières sont utilisés en Python, Perl , Ruby, PHP, Java, C, C++, par des programmes comme sed, awk, grep, vim, rename, ou encore des filtres dans apache et lighttpd ( mod_rewrite,​ vhosts ...), adblock dans firefox... Cette liste est bien sûr non exhaustive. 
 + 
 +----------------- 
 + 
 +Rédigé par : [[:​utilisateurs:​qazer|jeromeg]],​ ptitdav69 et Wazzaaabid
  • projets/ecole/scripting/initiation_au_shell.1175850637.txt.gz
  • Dernière modification: Le 24/05/2007, 19:12
  • (modification externe)