Protokolldatei nach Datum teilen

7

Ich habe eine Protokolldatei mit diesem Protokollformat:

###<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

Wie teile ich diese Protokolldatei nach Datum in Dateien YYYY_MM_DD.log auf?

tm4ig
quelle
3
Vielleicht hilft Ihnen logrotate , es ist ziemlich einfach zu bedienen.
Armita
Verwenden Sie den axeBefehl.
Oarfish

Antworten:

7

Eine perlLösung, die GNU nutzt date, um die Daten zu konvertieren:

perl -ne 'if(/^###<(.*)>/){
            chomp($d=`date -d \"$1\" +%Y_%m_%d`);
            $name="$d.log"
          } 
          open(my $fh,">>","$name"); 
          print $fh $_;' file.log 

Erläuterung

  • -ne: Lesen Sie die Eingabedatei zeilenweise (speichern Sie jede Zeile als spezielle Variable $_) und wenden Sie das von -ejeder Zeile angegebene Skript an.
  • if(/^###<(.*)>/): Wenn die Zeile mit beginnt ###<, erfassen Sie alles zwischen dem <>as $1(das tun die Klammern).
  • chomp($d=Datum -d "$ 1" +% Y_% m_% d );: Der dateBefehl formatiert das Datum neu. Zum Beispiel:

    $ date -d "Sep 1, 2016 1:00:01 AM" +%Y_%m_%d
    2016_09_01
    

    Das chompentfernt die letzte neue Zeile aus dem Ergebnis von, datedamit wir sie später verwenden können.

  • $name="$d.log": Wir speichern das Ergebnis des dateBefehls plus .logals Variable $name.
  • open(my $fh,">>","$name");: Öffnen Sie die Datei $nameals Dateihandle $fh. Machen Sie sich keine Sorgen, wenn Sie nicht wissen, was ein Dateihandle ist. Dies bedeutet nur, dass print $fh "foo"es gedruckt foowird $name.
  • print $fh $_;: Druckt die aktuelle Zeile in die Datei, auf die das Dateihandle $fhzeigt. Drucken Sie die Zeile also in die aktuell gespeicherte Zeile $name.
Terdon
quelle
6

Ein Ansatz zur Lösung dieses Problems könnte die Verwendung von awk sein. Zum Beispiel dieser Befehl:

awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file

sollte die Datei in die Dateien aufteilen und die Datumsfelder als Dateinamen verwenden

user000001
quelle
Nett! Beachten Sie, dass dadurch Dateien erstellt werden, die aufgerufen werden. 2016_Sep_1.logStattdessen hat 2016_09_01das OP meiner Meinung nach darum gebeten.
Terdon
@terdon: Das ist richtig. Ich habe es der Einfachheit halber so belassen, aber die Antwort könnte angepasst werden, um den dateBefehl wie in den beiden anderen Antworten zu verwenden.
user000001
6

Mit 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

Lesbare Form:

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
  • /^#+<[^>]+>$/Entspricht den Zeilen, die Datumsangaben enthalten, wird der von umgebene {}Block nur ausgeführt, wenn die Bedingung übereinstimmt. Wenn Übereinstimmungen vorliegen, erhalten wir das Datum im gewünschten Format, indem wir einen externen dateBefehl verwenden, die Ausgabe in einer Variablen filespeichern und den Inhalt der Variablen linesbis zur Datei file(aus dem vorherigen Block) speichern und die Variable dann lineserneut mit der Zeile instanziieren

  • Für alle anderen Zeilen verketten wir die Zeilen als Variable lines

  • Der letzte ENDBlock wird durch Einfügen in den Block gespeichert

heemayl
quelle