J'utilise Bash Shell pour traiter certains fichiers journaux, que je dois mettre dans un fichier CSV. Les informations dont j'ai besoin sont date et heure de début du processus, date et heure de fin du processus, ID de processus et message
Ce que j'ai fait, les lignes de grep comprenant le processus démarré et mis dans un fichier, puis Grep a mis fin aux processus et les a placés dans un deuxième fichier. Une fois cela fait, je prends chaque fichier et utilise awk pour scinder et extraire les informations nécessaires, voici une paix de code que j'utilise,
input=starts.txt
while IFS= read -r line
do
procs=`echo $line | awk '{ print $6;}'
date_s=`echo $line | awk '{ print $1;}'`
time_s=`echo $line | awk '{ print $2;}'`
m1=`echo $line | awk '{ print $3;}'`
m2=`echo $line | awk '{ print $4;}'`
m3=`echo $line | awk '{ print $5;}'`
m4=`echo $line | awk '{ print $7;}'`
m5=`echo $line | awk '{ print $8;}'`
m6=`echo $line | awk '{ print $9;}'`
echo $procs ";" $date_s ";" $time_s ";" $m1 $m2 $m3 $m4 $m5 $m6
one < "$input" > result.csv
Les lignes ont le format suivant:
02/01/2018 10:32:35 ANR4930I Reclamation process 1320 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
J'ai deux problèmes maintenant:
Je lis votre tâche comme suit: "déplacez le champ 5 (process number
) au premier plan, puis affichez les 3 premiers champs séparés par ;
, suivis de ;
, puis du reste.
En Perl, je le ferais comme ça (en une ligne):
Perl -a -n -l -e \
'unshift @F, splice(@F, 5, 1);
print join(";", @F[0..2]), ";@F[3..$#F]";' \
< input.txt > output.csv
Résultat:
input.txt
:
02/01/2018 10:32:35 ANR4930I Reclamation process 1320 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
02/01/2018 10:32:35 ANR4930I Reclamation process 4567 started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
output.csv
:
1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
4567;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)
Perl -a -n -l -e
@F
\n
) également comme séparateur de sortie (assez simplifié)unshift @F, splice(@F, 5, 1);
@F
(qui contient une ligne de votre fichier d'entrée divisé en espaces) et ajoute 5th élément devant le tableau @F
.print join(";", @F[0..2]), ";@F[3..$#F]";'
@F
avec ;
entre-deux, puis;
puis du reste du tableau @F
à partir du 3rd élément jusqu’à la fin avec un espace comme séparateur. (print "@any_array"
imprime les éléments séparés par un espace.)Si vous voulez le même code qu'un script (disons format-messages.pl
], il est légèrement différent, car la ligne de commande bascule vers Perl (qui manque maintenant) ajoute implicitement du code qui doit maintenant être ajouté explicitement. (Oui, il y a sont d'autres moyens, mais ...)
#!/usr/bin/env Perl
use strict;
use warnings;
while(<>) {
my @F = split;
unshift @F, splice(@F, 5, 1);
print join(";", @F[0..2]), ";@F[3..$#F]\n";
}
Faites un chmod +x format-messages.pl
puis exécutez ce script avec ./format-messages.pl < input.txt > output.csv
La plus grande amélioration consistera à éviter complètement la boucle Shell et à traiter chaque enregistrement (ligne) directement dans Awk. Par exemple:
$ awk '{
printf("%s;%s;%s;", $6, $1, $2)
for(i=3; i<NF;i++) {
if(i==6) continue;
printf("%s ", $i)
}
printf("%s\n",$NF)
}' input
1320;02/01/2018;10:32:35;ANR4930I Reclamation process started for primary storage pool VM_VTL_POOL automatically, threshold=75, duration=None. (PROCESS: 1320)