Voici en quelques exemples, quelques indices de l'incroyable efficacité de la lessive Sed couplée au détergent Awk.
Remplacer toutes les occurences du mot “tache” par le mot “blancheur” dans le fichier mon_linge, on redirige le tout vers le fichier mon_linge_propre :
$ sed s/tache/blancheur/g mon_linge > mon_linge_propre
Remplacer tous les debuts de ligne par un “.” dans le fichier mon_linge, on redirige le tout vers mon_linge_bien_range :
$ sed s/^/./ mon_linge > mon_linge_bien_range
Remplacer tous les fins de ligne par un “.” dans le fichier mon_linge, on redirige le tout vers mon_linge_bien_range :
$ sed s/$/./ mon_linge > mon_linge_bien_range
Effacer toutes les lignes contenant le mot “tache” dans le fichier mon_linge, on redirige le tout vers le fichier mon_linge_propre :
$ sed /tache/d mon_linge > mon_linge_propre
Effacer toutes les lignes contenant le mot “tache” et remplacer tous les fins de ligne par un “.”, on redirige vers mon_linge_qui_sent_bon :
$ sed -e 's/$/./' -e 's/.*tache.*/\\0/' > mon_linge_qui_sent_bon
Afficher la 2eme colonne ( PID ) du resultat d'un ps aux :
$ ps aux|awk '{print $2}'
Afficher la 2eme colonne ( PID ) du resultat d'un ps aux en le faisant précéder d'un label :
$ ps aux|awk '{printf("PID: %s\n"), $2}'
Afficher la 2eme colonne ( PID ) du resultat d'un ps aux en le faisant précéderd'un label et en affichant l'utilisateur :
$ ps aux|awk '{printf("PID: %s utilise par %s\n"), $2, $1}'
Afficher l'/etc/passwd bien rangé :
$ awk -F: '{printf("Utilisateur: %s\nUID: %s\nGID: %s\nNom: %s\nHome: %s\nShell: %s\n", $1, $3, $4, $5, $6, $7)}' /etc/passwd
Afficher les users dont le shell est /bin/bash
awk -F: '$7=="/bin/bash" {print $1}' /etc/passwd
Utiliser les fonctions mathématiques :
$ echo "3 4" | awk '{print int($1+$2)}'
(affiche normalement 7, si tout se passe bien)
Utiliser les fonctions mathématiques (2):
ls -1sk /usr/bin | sort -n | awk '$1 > 500'
(affiche le nom des executables de /usr/bin dont la taille est supérieure a 500 k)
Le but de la manip était de passer de proftpd “classic” à proftpd-mysql+proftpd administrator (http://proftpd-adm.sourceforge.net/)
En entrée, un fichier de type passwd contenant username, passwd, uid, gid, etc..
$ cat /etc/proftpd.passwd 64telecom:$1$YVOCtxyK$jQEyhesyMwECPgHP0Yh1O0:111:65534::/home/commun/ftp-externe/64telecom:/bin/false bgsa:$1$Dzy3LXzx$5z4OrKHQjxEINcg5XIrBl.:111:65534::/home/commun/ftp-externe/bgsa:/bin/false mpsftp:$1$dNm0LqxW$E7t4TuNkv/srqp4HRL3Xz1:111:65534::/home/commun/ftp-externe/mpsftp:/bin/false mpsftp1:$1$YTfhVzwS$iBUOELFxp.fT3tH7GjPd5.:111:65534::/home/commun/ftp-externe/mpsftp/mpsftp1:/bin/false .. (150 lignes)
En sortie, des INSERT INTO en veux-tu, en voilà, afin d'insérer tout ça dans une base de données MySQL. Un exemple ce que je voulais:
INSERT INTO usertable (userid, passwd, homedir, shell, uid, gid, count, lastlogin, lastlogout, expiration, disabled, det_name, det_mail, det_adress, det_notes) VALUES ('mobisfraf83', '$1$WVPoRVPU$gWEuzxgS7ZZ2mN/BYVedd0', '/home/commun/ftp-externe/mobisfraf83', '/bin/false', '2154', '10001', '0', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0', 'mobisfraf83', 'mobisfraf83', 'mobisfraf83', 'mobisfraf83');
Sed et Awk, c'est un peu la fusion de 2 super Sayen dans Dragon Ball Z. J'en veux pour exemple mon code:
#!/bin/sh a="2000" for i in `cat /etc/proftpd.passwd` do echo $i \ | cut -d":" -f 1,2,6 | \ sed 's/\:/ /g' | \ awk -v sq="'" '{print "INSERT INTO usertable (userid, passwd, homedir, shell, uid, gid, count, lastlogin, lastlogout, expiration, disabled, det_name, det_mail, det_adress, det_notes) VALUES ('"'"'" $1 "'"'"', " "'"'"'" $2 "'"'"', " "'"'"'" $3 "'"'",' " sq "/bin/false" sq ", " sq "111" sq ", " sq "10001" sq ", " sq "0" sq ", " sq "0000-00-00 00:00:00" sq ", " sq "0000-00-00 00:00:00" sq ", " sq "0000-00-00 00:00:00" sq ", " sq "0" sq ", '"'"'" $1 "'"'"', " "'"'"'" $1 "'"'"', " "'"'"'" $1 "'"'"', " "'"'"'" $1 "'"'"'" ");"}' | \ sed s/111/$a/g a=$(expr $a + 1) done
Explications: echo affiche sur la sortie les lignes du fichier 1 à 1. cut découpe et prend les colonnes 1, 2, 6 avec comme séparateur “:”. sed remplace les 2 points par une espace. awk fait son boulôt en affichant ce qui reste là où je lui demande de les afficher ($1, $2, $3). À noter: le garçon est TRES CHIANT en ce qui concerne le traitement des singles quotes (vraiment!). J'ai bidouillé un peu, mais ça fonctionne (il existe plusieurs manières de traiter les singles quotes, Google is your friend). sed termine la marche en remplaçant la chaine 111 par une variable que j'incrémente de 1 à chaque fois et qui commence à 2000 (l'UID des utilisateurs).
On sauvegarde et on execute. 150 requêtes en un claquement de doigt. Moi je dis, MESSIEURS..
Mais subtil rebondissement, l'admin etant une grosse moule il ne supporte pas la taille gigantesque de ce script et decide de l'ecrire un un seul statement de awk, evitant un nombre incalculable (enfin si, tres calculable) de generations de processus pour le reduire a un seul
awk -F: -v s="'" -v c=", " -v "a=2000" '{print "INSERT INTO usertable (userid, passwd, homedir, shell, uid, gid, count, lastlogin, lastlogout, expiration, disabled, det_name, det_mail, det_adress, det_notes) VAL UES (" s $1 s c s $2 s c s $6 s c s "/bin/false" s c s a++ s c s "10001" s c s "0" s c s "0000-00-00 00:00:00" s c s "0000-00-00 00:00:00" s c s "0000-00-00 00:00:00" s c s "0" s c s $1 s c s $1 s c s $1 s c s $ 1 s ");" }' /etc/proftpd.passwd
Des lors l'admin contemple son oeuvre et derriere son apparence de goret immonde se trouve une ame de poete, il lui faut utiliser les qualites intrinseques de awk et ne pas souiller son appel de vilains flags inutiles et reserves aux tacherons:
awk 'BEGIN { sep="\047, \047"; a=2000; FS=":" } {print "INSERT INTO usertable (userid, passwd, homedir, shell, uid, gid, count, lastlogin, lastlogout, expiration, disabled, det_name, det_mail, det_adress, det_notes) VALUES (\047" $1 sep $2 sep $6 sep "/bin/false" sep a++ sep "10001" sep "0" sep "0000-00-00 00:00:00" sep "0000-00-00 00:00:00" sep "0000-00-00 00:00:00" sep "0" sep $1 sep $1 sep $1 sep $1 "\047);" }' /etc/proftpd.passwd
Ici on utilise BEGIN qui est un pattern particulier utilise pour matcher avant la premiere ligne.
Notre admin, fort de sa maitrise nouvelle du puissant awk, decide qu'il a envie d'afficher les lignes de son fichier proftpd.passwd, mais a l'envers. Il se lance dans la reecriture du celebre tac:
awk 'END { for (i = NR - 1; i >= 0; i--) { print lines[i]; }} { lines[i++] = $0 }'
Ici c'est le pattern particulier END qui est utilise.
Note: Sed et Awk peuvent également etre utilisés en cascade ( pipe: | ) pour encore plus de fraicheur.