Mot-clé - Awk

Fil des billets

Conversion des fins de lignes entre Unix et Windows

C'est la méthode la plus simple que j'aie trouvée. Elle nécessite de disposer d'un awk autorisant l'emploi d'expressions rationnelles comme séparateur d'enregistrements (RS). De plus, elle marche sur des fichiers comportant à la fois des fins de lignes Unix et DOS, sans ajouter de lignes blanches parasites.

L'utilisation de la variable BINMODE[1] est optionnelle. Sur les awk compatibles, elle désactive les conversions implicites des fins de lignes.

Cette procédure a été testée avec gawk, mawk et busybox awk[2]. Elle ne marche pas avec le awk original.

Convertir des fins de lignes Unix (LF) en fins de lignes DOS (CR-LF)

Utiliser la commande awk suivante :

gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\r\n' '{ print }'

Par exemple :

gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\r\n' '{ print }' fichier.unix.txt > fichier.dos.txt

Pour vérifier le résultat (en remplaçant u8 par le code du codage utilisé si vous n'êtes pas en UTF-8[3]) :

# Sans conversion
echo -e 'essai\nessai\r\nessai' | recode u8..dump-with-names

# Avec conversion
echo -e 'essai\nessai\r\nessai' | gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\r\n' '{ print }' | recode u8..dump-with-names

Convertir des fins de lignes DOS (CR-LF) en fins de lignes Unix (LF)

Utiliser la commande awk suivante :

gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\n' '{ print }'

Par exemple :

gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\n' '{ print }' fichier.dos.txt > fichier.unix.txt

Pour vérifier le résultat (en remplaçant u8 par le code du codage utilisé si vous n'êtes pas en UTF-8) :

# Sans conversion
echo -e 'essai\nessai\r\nessai' | recode u8..dump-with-names

# Avec conversion
echo -e 'essai\nessai\r\nessai' | gawk -v BINMODE=3 -v RS='(\r\n|\n)' -v ORS='\n' '{ print }' | recode u8..dump-with-names

Notes

[1] Cf. la documentation de gawk et la documentation de mawk.

[2] L'option -v BINMODE=3 est inutile avec busybox awk.

[3] Par exemple l1 pour Latin 1 (ISO-8859-1) et l9 pour Latin 9 (ISO-8859-15), lancez recode -l pour obtenir la liste complète des codages.

De l'art de surveiller les scripts...

Écrire un script, c'est bien, mais, si le script est lancé automatiquement, il est judicieux de disposer d'un journal permettant de s'assurer de son bon fonctionnement[1]...

J'ai mis en place il y a peu un script chargé d'apprendre à spamassassin à reconnaître des messages indésirables. Ce script lance la commande sa-learn, et pour savoir s'il fonctionne bien, je veux savoir ce qu'a affiché sa-learn.

La commande logger

Pour enregistrer un message dans le journal système (/var/log/syslog[2] sur une distribution Débian), on peut utiliser une commande très pratique : logger.

Par exemple :

logger -p user.info -t mon_script "Mon message"

fera apparaître le message suivant dans le journal système :

Jun 21 22:12:24 mon_serveur mon_script: Mon message
Un premier essai

Il suffit donc de prendre les messages affichés par sa-learn et de les envoyer à logger :

MA_SORTIE="$( sa-learn --spam "${FICHIER}" 2>&1 )"
logger -p user.info -t mon_script "Resultat : ${MA_SORTIE}"

Cependant, nous ne pouvons pas être sûr que sa-learn renverra une seule ligne[3].

La même chose... En mieux

Le plus simple serait de fusionner les lignes affichées par sa-learn avant de les enregistrer dans le journal[4].

Ce que l'on peut faire simplement une ligne de awk :

sa-learn --spam "${FICHIER}" 2>&1 | gawk -v ORS="" 'NR > 1 { print " -/- " } ; { print }'

Donc, au bout du compte, c'est tout simple :

RESULTAT_COMMANDE="$( sa-learn --spam "${FICHIER}" 2>&1 | gawk -v ORS="" 'NR > 1 { print " -/- " } ; { print }' )"
logger -p user.info -t mon_script "sa-learn => ${RESULTAT_COMMANDE}"

En deux lignes, on lance sa-learn et on renvoie son résultat dans le journal système.

Notes

[1] Les programmes informatiques sont comme ça, si personne ne les surveille, ils font n'importe quoi.

[2] Le fichier journal utilisé dépendra du paramétrage du démon syslogd, de la priorité choisie (ici, info) et de la catégorie du message (ici, user)

[3] En général, les messages des journaux systèmes sont sur une seule ligne, ce qui permet de les exploiter simplement avec des outils Unix comme grep et logcheck.

[4] Attention ! On parle ici de fusionner une ou deux lignes, pas plus.