Podziel plik dziennika według daty

7

Mam plik dziennika z tym formatem dziennika:

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

Jak podzielić ten plik dziennika według daty na pliki YYYY_MM_DD.log?

    
zadawane tm4ig 19.09.2016, 13:22
źródło

3 odpowiedzi

7

Rozwiązanie perl , korzystając z GNU date do konwersji dat:

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

Objaśnienie

  • -ne : odczytaj plik wejściowy wiersz po wierszu (zapisz każdą linię jako specjalną zmienną $_ ) i zastosuj skrypt podany przez -e do każdego wiersza.
  • if(/^###<(.*)>/) : jeśli linia zaczyna się od ###< , przechwytuj wszystko pomiędzy <> jako $1 (to robi nawias).
  • chomp($d= data -d \ "1 $ \" +% Y_% m_% d ); : polecenie date zmienia format daty. Na przykład:

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

    chomp usuwa końcowy znak nowej linii z wyniku date , abyśmy mogli go użyć później.

  • $name="$d.log" : zapisujemy wynik polecenia date plus .log jako zmienną $name .
  • open(my $fh,">>","$name"); : otwórz plik $name jako uchwyt pliku $fh . Nie martw się, jeśli nie wiesz, czym jest uchwyt pliku, oznacza to tylko, że print $fh "foo" wyświetli foo na $name .
  • print $fh $_; : wypisz bieżący wiersz do pliku, do którego odnosi się plik $fh . Więc wypisz linię do tego, co jest aktualnie zapisane jako $name .
odpowiedział terdon 19.09.2016, 14:15
źródło
6

Jednym ze sposobów rozwiązania tego problemu może być użycie awk. Na przykład to polecenie:

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

powinno podzielić plik na pliki, używając pól daty jako nazw plików

    
odpowiedział user000001 19.09.2016, 14:12
źródło
6

Z 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

Czytelny formularz:

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
  • /^#+<[^>]+>$/ odpowiada wierszom zawierającym daty, porcja otoczona {} zostanie uruchomiona tylko wtedy, gdy warunek się zgadza. Jeśli pasuje, otrzymujemy datę w pożądanym formacie, używając zewnętrznego polecenia date i zapisując wynik w zmiennej file , i zachowując zawartość zmiennej lines , o ile plik file (z poprzedniej porcji), a następnie utworzyć instancję zmiennej lines ponownie z linią

  • Dla wszystkich innych linii łączymy linie jako zmienną lines

  • Ostatni fragment jest zapisywany poprzez wstawienie bloku END

odpowiedział heemayl 19.09.2016, 14:14
źródło

Przeczytaj inne pytania na temat tagów