J'ai un fichier journal avec ce format de journal:
###<Aug 8, 2016 11:59:05 PM>
different text
...
different text
###<Aug 15, 2016 9:10:55 AM>
different text
...
...
...
different text
###<Aug 22, 2016 10:02:17 PM>
different text
...
...
...
...
different text
###<Sep 1, 2016 1:00:01 AM>
different text
###<Sep 7, 2016 3:00:01 PM>
different text
...
...
different text
Comment diviser ce fichier journal par date en fichiers YYYY_MM_DD.log?
Une solution Perl
, tirant parti de GNU date
pour convertir les dates:
Perl -ne 'if(/^###<(.*)>/){
chomp($d=`date -d \"$1\" +%Y_%m_%d`);
$name="$d.log"
}
open(my $fh,">>","$name");
print $fh $_;' file.log
-ne
: lit ligne par ligne le fichier en entrée (en enregistrant chaque ligne comme variable spéciale $_
) et applique le script donné par -e
à chaque ligne.if(/^###<(.*)>/)
: si la ligne commence par ###<
, capturez tout ce qui se trouve entre <>
comme $1
(c'est ce que font les parenthèses).chomp($d=
date -d\"$ 1 \" +% Y_% m_% d);
: la commande date
reformate la date. Par exemple:
$ date -d "Sep 1, 2016 1:00:01 AM" +%Y_%m_%d
2016_09_01
La chomp
supprime la nouvelle ligne finale du résultat de date
afin que nous puissions l'utiliser ultérieurement.
$name="$d.log"
: nous enregistrons le résultat de la commande date
plus .log
sous la forme de la variable $name
.open(my $fh,">>","$name");
: ouvre le fichier $name
en tant que descripteur de fichier $fh
. Ne vous inquiétez pas si vous ne savez pas ce qu'est un descripteur de fichier, cela signifie simplement que print $fh "foo"
imprimera foo
dans $name
.print $fh $_;
: affiche la ligne en cours dans le fichier que le fichier gère. $fh
pointe vers. Donc, imprimez la ligne dans tout ce qui est actuellement enregistré en tant que $name
.Une approche pour résoudre ce problème pourrait être d'utiliser awk. Par exemple, cette commande:
awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file
devrait scinder le fichier en fichiers, en utilisant les champs de date comme noms de fichier
Avec awk
:
awk '/^#+<[^>]+>$/ {if (lines) print lines >file; \
dt=gensub("^#+<([^>]+)>$", "\\1", $0)
dt_cmd="date -d \""dt"\" +%Y_%m_%d.log" \
dt_cmd | getline file; lines=$0; next}; \
{lines=lines ORS $0} END {print lines >file}' file.log
Forme lisible:
awk '
/^#+<[^>]+>$/ {
if (lines)
print lines >file
dt=gensub("^#+<([^>]+)>$", "\\1", $0)
dt_cmd="date -d \""dt"\" +%Y_%m_%d.log"
dt_cmd | getline file; lines=$0
next
}
{
lines=lines ORS $0
}
END {
print lines >file
}' file.log
/^#+<[^>]+>$/
correspond aux lignes contenant les dates. Le bloc entouré de {}
ne sera exécuté que si la condition est la même. Si les correspondances, nous obtenons la date au format souhaité en utilisant la commande externe date
, en enregistrant le résultat dans la variable file
, et en enregistrant le contenu de la variable lines
dans la mesure où le fichier file
(à partir du bloc précédent), puis instanciez à nouveau la variable lines
avec la ligne
Pour toutes les autres lignes, nous concaténons les lignes en tant que variable lines
Le dernier morceau est sauvegardé en mettant dans le bloc END