{{tag>console}} realisé par [[utilisateurs/va-nu-pied|flo|va-nu-pied]] ====== Sed - Cut ====== {{icons:iconnote.png }} >les possibilités de ces commandes en terme de syntaxe étant tellement vastes que nous n'aborderons que la partie émergée de l'iceberg (cette page étant bien évidemment perfectible dans le temps) ===== Présentation ===== **sed** et **cut** permettent de modifier ou de supprimer une partie d’une chaîne de caractères, par exemple pour remplacer un caractère par un autre dans un fichier, ou encore supprimer des chaînes de caractères inutiles. Ce sont des outils très puissants. ===== Utilisation ===== Pour utiliser **sed** ou **cut**, vous devez lui fournir une chaîne à traiter. Cette chaîne peut provenir : * d'un fichier * d'une variable En règle générale la syntaxe est de la forme \\ "s/[//occurrence_cherchée//]/[//occurrence_de_substitution//]/[//comportement//]" ==== sed - cut et les fichiers ==== Pour pouvoir traiter un fichier, il est nécessaire de lire le fichier à **sed.** Nous utiliserons la commande **grep** sous la forme : \\ grep occurrence /fichier/a/parcourir | sed ... \\ grep occurrence /fichier/a/parcourir | cut ... \\ ou encore même conjointement \\ grep occurrence /fichier/a/parcourir | cut ... |sed ... ==== sed - cut et les variables ==== Pour nos exemples nous allons définir une variable à l'aide de la commande **export** florent@gentoo ~ $ export chaine="ceci est une chaine de caractères" florent@gentoo ~ $ Ainsi nous définissons la valeur de la variable $chaine. Nous pouvons à présent appeler cette variable au besoin. florent@gentoo ~ $ echo $chaine | sed -e "s/ /_/g" ceci_est_une_chaine_de_caractères florent@gentoo ~ $ {{icons:iconnote.png }} >Remplacer les espaces par des caractères est une des étapes importantes visant à substituer les caractères pouvant être mal interprétés par la suite. >> mplayer mon fichier.avi ne fonctionne pas tandis que \\ >> mplayer mon**_**fichier.avi fonctionnera >Le **g** positionné après l'occurrence de substitution ("s/ /_/**g**") indique à **sed** de se comporter de façon globale ("récursive") ===== Exemple : ===== Nous voulons récupérer l'//uid// ainsi que le //gid// d'un utilisateur en cours. Sous linux, l'utilisateur courant est défini dans la variable **$USER** \\ La preuve en est : echo $USER // retourne l'utilisateur en cours // \\ l'//uid// et //gid// de l'utilisateur est stocké dans le fichier /etc/passwd. Dans un premier temps récupérons la ligne concernant notre utilisateur florent@gentoo ~ $ grep $USER /etc/passwd florent:x:1000:1000::/home/florent:/bin/bash florent@gentoo ~ $ // parcourir le fichier // **/etc/passwd** // et retourner la ligne concernant le nom de l'utilisateur en cours // \\ vous me direz : parfait ! Et bien nous avons notre //uid// et //gid//. Certes mais le résultat est difficilement exploitable vous en conviendrez. Nous allons donc séparer de façon distincte les deux valeurs. Il nous faut pour cela analyser le résultat de la commande précédente pour définir des règles de traitement : - //uid// et //gid// sont sous la forme de chiffres - les informations sont séparées par **:** - la liste des paths est introduite par **::** ces différentes remarques vont nous permettre de fixer des délimiteurs, isolons donc la chaîne précédant les **::** du reste de la chaîne florent@gentoo ~ $ grep $USER /etc/passwd | sed "s/::/%/" |cut -d'%' -f1 florent:x:1000:1000 florent@gentoo ~ $ // parcourir le fichier // **/etc/passwd** // et retourner la ligne concernant le nom de l'utilisateur en cours // **|** // remplacer **(s)** les // **::** // par // **%** // dans le résultat// **|** // dans le résultat, supprimer l'occurrence // **%** // **(-d'%')** et tout ce qui la suit la première occurrence vérifiant **(-f**1**)**// \\ \\ Le principe est donc maintenant posé. Effectuons une dernière action afin de mettre en forme le résultat : florent@gentoo ~ $ grep $USER /etc/passwd | sed "s/::/%/g" |cut -d'%' -f1 |cut -d'x' -f2 |sed -e "s/:\([0-9][0-9]*\)/UID=\1\n/" -e "s/:\([0-9][0-9]*\)/GID=\1/" UID=1000 GID=1000 florent@gentoo ~ $ Décortiquons les différentes étapes du traitement : | ^ Commande ^ Sortie ^ ^ origine | grep $USER /etc/passwd | **florent**:x:1000:1000::/home/**florent**:/bin/bash | ^ Etape 1 | sed "s/::/%/" | florent:x:1000:1000**%**/home/florent:/bin/bash | ^ Etape 2 | cut -d'%' -f1 | florent:x:1000:1000 | ^ Etape 3 | cut -d'x' -f2 | :1000:1000 | ^ Etape 4 | sed -e "s/:\([0-9][0-9][0-9][0-9]\)/UID=\1\n/" -e "s/:\([0-9][0-9][0-9][0-9]\)/GID=\1/" | UID=1000 \\ GID=1000 | plus simple : sed -n -e "/`echo $USER`/s/[^:]*:[^:]*:\([^:]*\):\([^:]*\):.*/UID=\1\nGID=\2/p" /etc/passwd Voila les étapes du traitement d'une chaîne de caractères avec quelques détails à ne pas oublier. {{installation:warning.png }} > * L'ordre de traitement est crucial > * Le délimiteur utilisé par **cut** ne peut excéder 1 caractère d'où l'étape 1 visant à remplacer deux caractères consécutifs par un caractère unique remarquable utilisé dans l'étape 2 > * L'étape 4 introduit quelques syntaxes intéressantes : > - sed -e "[règle 1]" -e "[règle 2]" > - sed "s/\(occurrence\)/%\1%/" qui retourne %occurrence% > - sed "s/\(occurrence\)/\1\n/" qui insère un retour charriot à la fin de l'occurrence ===== Astuces en Vrac ===== une syntaxe intéressante peut s'avérer parfois très utile notamment pour des occurrences de type chemin de dossier **/chemin/de/fichier**. En effet la présence de caractères **/** peut poser certains problèmes. Afin de pallier cela il est possible d'utiliser une syntaxe différente que voici : sed -e "s|/chemin/vers/un/fichier|/chemin/vers/un autre|" ainsi les **/** seront correctement interprétés. Si vous désirez modifier des occurrences dans un fichier vous pouvez préférer l'option -i qui permet d'éditer un fichier. Ainsi : sed -i "s/une occurrence/une autre/g" /un/fichier.txt Va remplacer toutes les occurrences **une occurrence** par **une autre** dans le fichier **/un/fichier.txt** === Fin de ligne === sed traite les lignes individuellement (l'une aprés l'autre), il semble donc, au premier abord, incapable de joindre deux lignes séparées par un motif comportant le retour chariot (\n). Heureusement cette difficulté n'est qu'apparente : il suffit de lui indiquer de traiter les deux lignes. Exemple : joindre à la ligne précédente chaque ligne commençant par un espace (soit substituer un espace simple aux deux caractères saut de ligne puis espace) sed 'N;s/\n / /g;P;D;' fichier Dans cet exemple "N" indique à sed de lire également la ligne suivante, "P" d'afficher le résultat et "D" d'effacer la ligne suivante (puisqu'elle a déjà été lue). Les différentes commandes sont séparées par des points-virgules. Le texte suivant : Aujourd'hui Ubuntu est incontestablement un beau succès. On ne peut que s'en réjouir. L'avenir appartient aux heureux utilisateurs de cette distribution. devient : Aujourd'hui Ubuntu est incontestablement un beau succès. On ne peut que s'en réjouir. L'avenir appartient aux heureux utilisateurs de cette distribution. Et pour finir la commande à saisir pour transformer les fins de lignes DOS (\r\n] en fins de ligne UNIX (\n) : sed 's/^M$//' fichier Où "^M" représente \r. en mode console l'affichage de ^M peut s'obtenir en saisissant CTRL+V puis CTRL+M === Pour conclure ===== Vous l'aurez bien compris avec ces deux commandes en poche vous pouvez foncièrement faire tout ce que vous souhaitez. Je ne peux que vous encourager à lire la documentation concernant l'usage et la syntaxe de ces deux commandes que vous trouverez en tapant respectivement **man sed** et **man cut** \\ Il ne vous reste plus qu'à intégrer ces connaissances à vos [[:tutoriel:script_shell|script shell]] ===== Liens ===== [[http://www.panix.com/~elflord/unix/sed.html|Tutorial SED]] (en) : tutoriel qui explique entres autres comment faire de la recherche multiligne [[http://www.commentcamarche.net/faq/9536-sed-introduction-a-sed-part-i|Explications completes]] (fr) : très bon tutoriel sur l'utilisation de sed ainsi que de tres bonnes explications du fonctionnement [[http://www.shellunix.com/sed.html | Tutorial SED]] (fr) : petit tutoriel simple en français [[http://www.scotchlinux.tuxfamily.org/doc/sed.php|Man de SED illustrée]](fr): Ce qu' on apprend à partir de la page de manuel de sed. [[http://man2linux.blogspot.com/2010/11/sed.html|SED explications]] (fr) : Exemples sur l'utilisation de la commande SED [[http://www.neoflow.fr/tutoriels.item.237/Trier-les-lignes-d-un-fichier-selon-un-mot.html|Trier les lignes d'un fichier selon un mot avec SED]] [[http://www.neoflow.fr/tutoriels.item.236/Enlever-les-commentaires-d%27un-fichier.html|Enlever les commentaires d'un fichier avec SED]] [[https://fr.wikipedia.org/wiki/Stream_Editor|page Wikipedia]] [[http://forum.macbidouille.com/index.php?showtopic=128499|supprimer \n]] [[http://www.commentcamarche.net/faq/5978-sed-conversion-retours-chariots-dos-crlf-unix-lf|retour chariot DOS]] ---- Contributeurs : [[utilisateurs/va-nu-pied|flo|va-nu-pied]]