web-dev-qa-db-fra.com

Sélectionnez le texte restant dans une ligne d'un fichier journal

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:

  1. La boucle while ne se termine pas.
  2. Après avoir extrait l'heure/la date et l'ID de processus, je souhaite placer le message restant dans un champ séparé, sans prendre Word par Word ni les concaténer (m1 m2 m 3 ...). Aussi, s'il y a des améliorations à apporter à mon code.
2
Aziz Azizos

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)

Explication:

Perl -a -n -l -e

  • scinder chaque ligne d'entrée en blanc et placer le résultat dans le tableau prédéfini @F
  • traiter chaque ligne d'entrée (mais ne pas l'imprimer pour le moment)
  • utiliser le séparateur d'entrée (\n) également comme séparateur de sortie (assez simplifié)
  • lancer l'expression suivante pour chaque ligne d'entrée

unshift @F, splice(@F, 5, 1);

  • enlève le 5th élément (nombre = 1) du tableau @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]";'

  • imprime les 2 premiers éléments de @F avec ; entre-deux, puis
  • suivi d'un littéral ; 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

4
PerlDuck

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)
5
steeldriver