Trucs de geek : la commande sed
Lorsque vous souhaitez modifier un fichier texte vous aurez surement besoin de recourir à la commande "sed" qui vous permettra des remplacements sur les lignes sélectionnées. Son principe de fonctionnement est simple : la commande reçoit un flux de données, sélectionne des lignes et les traite et les écrit sur la sortie standard (l'écran).
La commande prendra la forme suivant :
$ sed le_fichier.txt -e "les commandes"
Basiquement sed vous permet d'afficher le contenu d'un fichier.
Afficher certaines lignes :
$ sed -n "10,12p" /etc/passwd
N'affiche que les lignes 10 à 12 du fichier.
Pour n'afficher que la première ligne :
$ sed -n "1p" /etc/passwd
On peut aussi filtrer les lignes dans un fichier :
$ sed -n '/linux/p' fichier_entree.txt > fichier_sortie.txt
Ainsi seules les lignes contenant "linux" seront dans le fichier en sortie. C'est l'équivalent d'un grep.
Autre cas : on n'afficher que les lignes 3 à 10 d'un fichier :
$ sed -n "3,10 p" /etc/samba/smb.conf
Pour ne pas afficher les lignes qui sont des commentaires (commençant par un #) :
$ sed /etc/samba/smb.conf -e '/^#.*$/d'
On prend les lignes qui commencent (^) par un (#) et qui se poursuivent pas un nombre quelconque (*) de caractères (.), et on choisit de les détruire (d) du résultat. On peut donc récupérer un version allégée du fichier de configuration.
Continuons par les substitutions dans les lignes. Le premier exemple permet de substituter un mot par un autre :
Soit le fichier ".smbcredentials" qui contient les lignes suivantes :
username=jfd
password=54mlkjhg
Pour modifier le mot de passe on va écrire un script qui va substituer le nouveau mot de passe à l'ancien. Avec sed cela va ressembler à cela :
mdp=$( cat .smbcredentials|grep password|cut -d'=' -f 2)
sed -i "s/$mdp/nouveau_mot_de_passe/"
L'option "-i" modifie directement le fichier. La première instruction retrouve l'ancien mot de passe. Et sed réalise la changement. Avec sed toutes les lignes sont lues et copiées en sortie mais seule la ligne correspondant au motif est modifiée car elle correspond au motif de recherche.
Autre exemple de substitution :
$ cat /etc/passwd |sed -e "s/:/*/g"
Qui affichera le fichier en question avec des "*" en guise de séparateur de champ.
Il est possible de modifier les séparateurs de champ quand on doit substituer des "/" entre autre. La formule suivante est donc tout à fait correcte :
$ sed -e "s|/root|/home|g" /etc/passwd
Si vous souhaitez que la modification ne tienne pas compte de la case, ajoutez l'option "i". Sit :
$ sed -e "s|/root|/home|gi" /etc/passwd
Si vous ne souhaitez réaliser les substitutions que sur certaines lignes continues :
$ sed -e "5,7 s|/root|/home|gi" /etc/passwd
Pour supprimer des lignes qui ne contiennent qu'un chiffre, on va utiliser une expression rationnelle :
$ cat test.txt | sed "s/^[0-9]\{,4\}//" > V.txt
La signification des caractères spéciaux est la suivante :
- ^ correspond au début d'une ligne
- $ correspond à la fin d'une ligne
- . correspond à n'importe quel caractère unique
- * correspond à aucune ou plusieurs occurrences du caractère qui précède
- [ ] correspond à n'importe lequel des caractères cités entre les crochets
Dans l'exemple ci dessus on sélectionne les lignes qui commencent (^) par un à 4 (\{,4\}) chiffres ([0-9]) et qui se comportent rien ensuite ($ indiquant la fin de la ligne). On substitue (s) à ces chiffres rien (//).
Autre exemple avec l'option "d". Dans un fichier de sous titre je veux supprimer les lignes qui commencent un heure au format "00:00:00". Je fais donc :
$ cat V.srt | sed -e '/^[0-9]\{2\}:.*$/d'> resultat.srt
Je ne copie pas en sortie (d) les lignes qui commencent (^) par deux (\{2\}) chiffres ([0-9]) suivi d'un ":" et d'un nombre quelconque de caractères.
Autre utilisation de l'option "d", ne recopier en sortie un fichier qu'à partir de la 10ème ligne :
$ sed "1,10d" /etc/passwd
N'affiche que les lignes commençant par "ava".
$ sed /etc/passwd -n -e '/^ava/p'
L'option "-n" permet de n'afficher que les lignes sélectionnées. L'option "-p" demande l'affichage sans traitement
Pour supprimer les lignes vides dans un fichier :
$ cat mon_fichier.txt |sed -e '/^$/d'
On n'affiche pas (d) les lignes qui commencent et qui finissent par rien.
Cela permet aussi d'ignorer des lignes dans un fichier :
$ sed '20,35d' myfile.txt
Affiche le fichier en question sauf les lignes 20 à 35.
Si les lignes ne sont pas consécutives il faut recourir à l'opérateur "-e" :
$ sed -n -e '5,7p' -e '10,13p' myfile.txt
Commenter une ligne qui contient une séquance particulière (on pourrait aussi la supprimer) :
$ sed -e 's/.*sequence.*/#$/g' fichier_entree.txt > fichier_sortie.txt
Ce qui est intéressant est la suite ".*" qui s'interprête comme un caractère quelconque répété un nombre de fois quelconque.
Pour supprimer une ligne :
$ sed test.txt -e "/.*JF.*/d" > test2.txt
el les lignes comprenant "JF" seront supprimées en sortie.
On peut ajouter une ligne aprés une ligne repérée par son contenu :
$ sed test.txt -e "/.*JF.*/a LUCIE" > test2.txt
On va ajouter le prénom "LUCIE" aprés la ligne qui contient "JF".
Il est possible de ne remplacer que certaines occurrences trouvées. Si votre fichier contient la ligne à modifier suivante :
linux is great os. unix is opensource. unix is free os.
Si vous voulez changer 'unix" en linux dans la seconde phrase vous ne pouvez pas utiliser le commutateur "g" en faisant "s/unix/linux/g" car cela changerait les deux occurrences 'unix". Il faut donc faire :
$ sed 's/unix/linux/2' mon_fichier.txt
produira la ligne suivante :
unix is great os. linux is opensource. unix is free os.
Il est possible aussi de ne réaliser une substitution qu'à partir d'une certaine occurrence :
$ sed 's/unix/linux/3g' mon_fichier.txt
Ne commence la substitution qu'à partir de la 3ème occurrence. On obtient donc :
unix is great os. unix is opensource. linux is free os.
Fait le 04/03/2016
- Identifiez-vous pour poster des commentaires
Commentaires récents