GNU/Linux >> Znalost Linux >  >> Linux

Sloučit podle data více souborů protokolu, které také obsahují nedatované řádky (např. trasování zásobníku)

Záludné. I když je to možné pomocí date a bash pole, to je skutečně věc, které by prospěl skutečný programovací jazyk. Například v Perlu:

$ perl -ne '$d=$1 if /(.+?),/; $k{$d}.=$_; END{print $k{$_} for sort keys(%k);}' log*
01:02:03.6497,2224,0022 foo
foo1
2foo
foo3
01:03:03.6497,2224,0022 FOO
FOO1
2FOO
FOO3
01:04:03.6497,2224,0022 bar
1bar
bar2
3bar

Zde je totéž nezhuštěné do komentovaného skriptu:

#!/usr/bin/env perl

## Read each input line, saving it 
## as $_. This while loop is equivalent
## to perl -ne 
while (<>) {
    ## If this line has a comma
    if (/(.+?),/) {
        ## Save everything up to the 1st 
        ## comma as $date
        $date=$1;
    }
    ## Add the current line to the %k hash.
    ## The hash's keys are the dates and the 
    ## contents are the lines.
    $k{$date}.=$_;
}

## Get the sorted list of hash keys
@dates=sort(keys(%k));
## Now that we have them sorted, 
## print each set of lines.
foreach $date (@dates) {
    print "$k{$date}";
}

Upozorňujeme, že to předpokládá, že všechny řádky data a pouze řádky data obsahují čárku. Pokud tomu tak není, můžete místo toho použít toto:

perl -ne '$d=$1 if /^(\d+:\d+:\d+\.\d+),/; $k{$d}.=$_; END{print $k{$_} for sort keys(%k);}' log*

Výše uvedený přístup potřebuje zachovat celý obsah souborů v paměti. Pokud je to problém, zde je jeden, který ne:

$ perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log* | 
    sort -n | perl -lne 's/\0/\n/g; printf'
01:02:03.6497,2224,0022 foo
foo1
2foo
foo3    
01:03:03.6497,2224,0022 FOO
FOO1
2FOO
FOO3    
01:04:03.6497,2224,0022 bar
1bar
bar2
3bar

Tento jednoduše vloží všechny řádky mezi po sobě jdoucí časová razítka na jeden řádek nahrazením nových řádků \0 (pokud to může být ve vašich souborech protokolu, použijte libovolnou sekvenci znaků, o kterých víte, že tam nikdy nebudou). Toto bylo předáno sort a poté tr získat řádky zpět.

Jak velmi správně zdůraznil OP, všechna výše uvedená řešení je třeba použít a nepočítat s tím, že soubory lze sloučit. Zde je jeden, který ano, ale který na rozdíl od ostatních bude fungovat pouze se dvěma soubory:

$ sort -m <(perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log1) \
            <(perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/' log2) | 
    perl -lne 's/[\0\r]/\n/g; printf'

A pokud uložíte příkaz perl jako alias, můžete získat:

$ alias a="perl -pe 's/\n/\0/; s/^/\n/ if /^\d+:\d+:\d+\.\d+/'"
$ sort -m <(a log1) <(a log2) | perl -lne 's/[\0\r]/\n/g; printf'

Linux
  1. Jak komprimovat více souborů v systému Linux

  2. Jak přesměrovat Stderr a Stdout na různé soubory a také zobrazit v terminálu?

  3. Příkaz k vyčištění starých souborů protokolu?

  1. Dd:Více vstupních souborů?

  2. 20 Soubory protokolu Linux, které jsou umístěny v adresáři /var/log

  3. Sloučit / převést více souborů PDF do jednoho PDF

  1. Počítejte řádky ve velkých souborech

  2. syntaxe konfiguračního souboru logrotate – je možné zadat více zástupných znaků?

  3. Přejmenujte více souborů, abyste odstranili společnou příponu z názvů souborů