Outils pour utilisateurs

Outils du site


linux:sed (lu 52772 fois)

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
linux:sed [26-02-2012 09:58]
127.0.0.1 modification externe
linux:sed [04-10-2020 12:00] (Version actuelle)
edmc73 [Remplacement / substitution]
Ligne 1: Ligne 1:
-===== sed =====+====== sed ======
  
-encore une ébauche d'un mémo...+===== Description ===== 
 +**sed** est un outils très puissant permettant de transformer le texte du flux entrant.
  
-J'avais besoin d'extraite un nom de fichier dans un fichier index.html+Doc très détaillé :  
 +  *  http://www.siteduzero.com/informatique/tutoriels/la-commande-sed/ 
 +  *  http://www.gentoo.org/doc/fr/articles/l-sed1.xml
  
  
-sed c'est de la forme : 's/ce_qu'on_cherche/ce_qu'on_met_à_la_place/  (s pour substitution) +===== Exemples ===== 
-  + 
-  +==== Remplacement / substitution ==== 
-  +Prenons un fichier exemple 
-D'abord ce qu'on cherche avec ça (en rouge la version regexp) :+<file> 
 +toto 1234 toto titi 
 +tata 4321 toto tutu 
 +</file> 
 + 
 +L'option ''-i'' permet d'écrire directement les modifications dans le fichier. Sans l'option, le résultat s'affiche à l'écran 
 + 
 +Pour remplacer  **toto** par **koko** on utilise le **s** pour substitution 
 +  sed -i 's/toto/koko/fichier.txt
    
-n'importe quoi, suivi d'une espace, suivi de url=' +<file> 
-.* url=' +koko 1234 toto titi 
-  +tata 4321 koko tutu 
-on peut capturer un truc pour le ressortir avec \1 plus tard, d'où les parenthèses +</file>
-\(  et plus loin  \) +
-  +
-tout sauf ', plein de fois (quand tu mets [^c] ca veut dire tout sauf c) +
-[^']* +
-  +
-suivi de : ' puis d'autres caractères. On se simplifie la vie, on va juste dire "suivi de n'importe quoi" +
-.* +
-  +
-d'où la regexp (sans les parenthèses) .* url='[^']*.* et avec les parenthèses .* url='\([^']*\).* +
-  +
-  +
-  +
-  +
-  +
-  +
-Si tu regardes ton nouveau truc que tu veux filtrer, tu vois qu'on passe de :+
  
-url='blablabla'+On peut remarquer que seule la 1ère occurrence est remplacée, pour remplacer toutes les occurrences, on utilise l'option **g** à la fin de la commande 
 +  sed -i 's/toto/koko/g' fichier.txt 
 +<file> 
 +koko 1234 koko titi 
 +tata 4321 koko tutu 
 +</file>
  
 +Pour ignorer la casse, on utilise l'option **I**
 +  sed -i 's/toto/koko/gI' fichier.txt
  
-à :+Remplacer un \ par / dans les path des #include dans un fichier .c 
 +  sed -i '/#include/s@\\@/@g' fichier.c 
 +  sed -i '/#include/s@\\@/@g' *.c 
 +  sed -i '/#include/s@\\@/@g' **/*.c 
 +   
 +Pour remplacer dans l'ensemble d'un projet dans des fichiers .c et .h
  
-url="blablabla"+  find . -name '*.[ch]' -exec sed -i '/#include/s@\\@/@g' {} \; 
 +et inversement 
 +  find . -name '*.[ch]' -exec sed -i '/#include/s@/@\\@g' {} \; 
 +==== Translittération ==== 
 +Pratique pour par exemple remplacer tous les e avec accent par un e sans accent. 
 +  sed -e 'y/éèêë/eeee/' fichier.txt 
 +   
 +Ou pour crypter/décrypter 
 +  sed -e 'y/abcdefghijklmnopqrstuvwxyz/mnopqrstuvwxyzabcdefghijkl/' fichier.txt 
 +   
 +==== Suppression ==== 
 +Pour supprimer la 1ère ligne d'un fichier 
 +  sed -e '1d' fichier.txt 
 +Pour supprimer toutes les lignes sauf la 1ère  
 +  sed -e '1!d' fichier.txt 
 +Pour supprimer les lignes de 3 à 7 
 +  sed -e '3,7d' fichier.txt 
 +Pour n'afficher que les lignes de 3 à 7 
 +  sed -e '3,7!d' fichier.txt
  
 +Pour supprimer toutes les lignes de commentaire qui commence par exemple par **#**, on utilise l'option **d** pour delete à la fin de la commande
 +  sed -e '/^#/d' fichier.txt
 +A contrario, si nous voulons que les lignes qui commencent par un #, on ajoute un **!** devans l'option **d**
 +  sed -e '/^#/!d' fichier.txt
 +  
 +Exemple avec un fichier de conf qui comporte des lignes commentés avec un **;** et qui comportent beaucoup de lignes vide.
 +  sed -e '/^[#;]/d;/^$/d' /etc/samba/smb.conf
 +Avec les **[ ]** et spécifie que la ligne commente par un **#** ou un **;**. Le **;** suivant veut dire que nous lançons une autre commande, celle ci dit que nous cherchons une ligne vide. **^** indique le début de la ligne et **$** la fin. **/d** on delete.
  
-  +Supprimer les lignes qui contient un message d'erreur 
-Il faut donc travailler avec des " dans sed, au lieu des '. Donc on passe de : +  sed -e '/HTTP acceptToo many open files/dpound.log.1 > pound.log.clean.1
-.* url='\([^']*\).+
-à :   +
-.* url="\([^"]*\).+
-  +
-  +
-Evidemment pour que sed ne merde pas, il faut soit utiliser des \" au lieu des " (sinon au premier " sed va croire que la commande s'arrête là), soit utiliser des ' ' pour englober la commande, à la place des " "Cette seconde solution est la plus simple. +
-  +
-Bilan : on passe de  +
  
-sed -e "s/.*url='\([^']*\).*/\1/"+Éliminer les espaces et tabulations 
 +En début de ligne 
 +  sed 's/^[ \t]*// 
 +  sed 's/^\s*//       # Utilisation du paramètre "\s" 
 +   
 +En fin de ligne 
 +  sed 's/[ \t]*$//' 
 +   
 +En début et fin de ligne 
 +  sed 's/^[ \t]*//;s/[ \t]*$//' 
 +==== Expressions régulières ==== 
 +Prenons le cas de la commande **df** qui permet d'afficher l'espace disque de notre machine. Nous aimerions récupérer ces données pour les transmettre dans un format CSV avec des **;** comme séparateur.
  
 +Nous devons travailler sur ce genre de donnée:
 +<file>
 +Sys. de fichiers      1K-blocs   Utilisé    Dispo. Uti% Monté sur
 +/dev/sda1             19222656   7174048  11072048  40% /
 +tmpfs                  4099408           4099408   0% /lib/init/rw
 +udev                   4094596       196   4094400   1% /dev
 +tmpfs                  4099408           4099408   0% /dev/shm
 +</file>
 +On va imaginer un découpage basic de la sorte
 +  champ1 champ2 champ3 champ4 champ5 champ6
 +Un champ est zéro ou plusieurs n'importe quel caractère ce qui se traduit parun point suivi d'une étoile
 +  .* .* .* .* .* .*
 +Comme on veut pouvoir récupérer ces champs, on va les mettre entre parenthèses mais pour que sed ne croit pas que l'on cherche des parenthèses, nous devons les échapper par un backslash
 +  \(.*\) \(.*\) \(.*\) \(.*\) \(.*\) \(.*\)
 +Maintenant entre chaque champ nous avons un ou plusieurs espaces, ou pourrait écrire l'expression [:space:]+ mais sed ne reconnait pas le caractère **+** permettant de dire que l'on veut au moins de une occurrence à plusieurs.
 +Il faudrait ruser en écrivant ceci [:space:][:space]* 
  
-à :+Nous allons faire plus simple en lançant une première commande permettant de remplacer toutes les suites d'espaces par un seul espace sur toutes les occurrences rencontrées sur la ligne. 
 +  sed -e 's/[ ][ ]*/ /g' 
 +On obtient au final la commande  
 +  df | sed -e 's/[ ][ ]*/ /g' -e 's/\(.*\) \(.*\) \(.*\) \(.*\) \(.*\) \(.*\)/\1;\2;\3;\4;\5;\6/'
  
-sed -e 's/.* url="\([^"]*\).*/\1/'+Si on voulait ne récupérer que le pourcentage d'occupation 
 +  df | sed -e '1d;s/.* \([0-9]*\)% .*/\1/' 
 +Ici on a rajouté **1d** qui permet de supprimer la 1ère ligne. 
 + 
 +===== Exemple en vrac ===== 
 + 
 +Source 
 +<code>dublablacodecode<a href="/chemin/bien/precis/fichier.xyz">OnSenFoutDuNom</a>dublablacode 
 +dublablacodecode<a href="/chemin/bien/precis/fichier2.xyz">OnSenFoutDuNom</a>dublablacode</code> 
 + 
 +Résultat 
 +<code>fichier.xyz 
 +fichier2.xyz</code> 
 + 
 +Sed 
 +<code>sed -r 's/.*href=".*[$/](.*)".*/\1/' fichierSource</code> 
 + 
 +==== Extraire la date et la reformaté dans un nom de fichier ==== 
 + 
 +   
 +  $ echo Pict_20140215_0945.jpg | sed -r 's/.*([0-9]{4})([0-9]{2})([0-9]{2})_([0-9]{2})([0-9]{2}).*/\3-\2-\1 \4:\5/' 
 +  15-02-2014 09:45 
 + 
 +==== Extraire la valeur d'un test avec hdparm ==== 
 +On veut récupérer la valeur 64.66 
 +<code># hdparm -t /dev/sda 
 + 
 +/dev/sda: 
 + Timing buffered disk reads: 198 MB in  3.06 seconds =  64.66 MB/sec</code> 
 + 
 +  hdparm -t /dev/sda | sed -r '/Timing/!d;s/.*=\s*(.*MB.*/\1/' 
 +   
 +Avec le ''/Timing/!d'' on garde que la ligne qui contient le mot Timing.\\ 
 +''.*'' n'importe quoi jusqu'au ''='' suivi ou non de plusieurs espace\\ 
 +On prend la valeur jusqu'à rencontrer un espace suivi de ''MB'' et n'importe quoi. 
 + 
 + 
 +==== Connaitre les machines connectées à notre serveur NFS ==== 
 + 
 +<code>netstat -alp | egrep 'nfs(.*)ESTABLISHED' | sed -r 's/.* ([a-z0-9-]*\.[a-z0-9-]*\.[a-z0-9-]*).*/\1/'</code> 
 + 
 + 
 + 
 +===== Regexp extended ===== 
 + 
 +On peut mettre l'option -r à la place de l'option -e et voici la différence 
 + 
 +>Appendix A Extended regular expressions 
 +
 +>The only difference between basic and extended regular expressions is in the behavior of a few characters: ‘?’, ‘+’, parentheses, and  braces (‘{}’). While basic regular expressions require these to be escaped if you want them to behave as special characters, when using extended regular expressions you must escape them if you want them to match a literal character. 
 +
 +>Examples: 
 +
 +>abc? -> ‘abc\?’ when using extended regular expressions. It matches the literal string ‘abc?’.  
 +>c\+ ->  ‘c+’ when using extended regular expressions. It matches one or more ‘c’s.  
 +>a\{3,\} -> ‘a{3,}’ when using extended regular expressions. It matches three or more ‘a’s.  
 +>\(abc\)\{2,3\} -> ‘(abc){2,3}’ when using extended regular expressions. It matches either ‘abcabc’ or ‘abcabcabc’.  
 +>\(abc*\)\1 -> ‘(abc*)\1’ when using extended regular expressions. Backreferences must still be escaped when using extended regular expressions.
  
  
-  
-Juste une inversion des types de guillemets en fait ;)  
linux/sed.1330246692.txt.gz · Dernière modification: 04-04-2013 22:05 (modification externe)