GNU/Linux >> Linux Esercitazione >  >> Linux

Unisci per data più file di registro che includono anche righe non datate (ad es. tracce di stack)

Scaltro. Mentre è possibile utilizzare date e bash array, questo è davvero il tipo di cosa che trarrebbe vantaggio da un vero linguaggio di programmazione. In Perl per esempio:

$ 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

Ecco la stessa cosa non condensata in uno script commentato:

#!/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}";
}

Tieni presente che ciò presuppone che tutte le linee di data e solo le righe della data contengono una virgola. In caso contrario, puoi utilizzare questo:

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

L'approccio di cui sopra deve mantenere in memoria l'intero contenuto dei file. Se questo è un problema, eccone uno che non lo fa:

$ 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

Questo mette semplicemente tutte le righe tra timestamp successivi su una singola riga sostituendo le nuove righe con \0 (se questo può essere nei tuoi file di registro, usa qualsiasi sequenza di caratteri che sai non ci sarà mai). Questo è passato a sort e poi tr per recuperare le linee.

Come sottolineato molto correttamente dall'OP, è necessario ricorrere a tutte le soluzioni di cui sopra e non tenere conto del fatto che i file possono essere uniti. Eccone uno che funziona ma che, a differenza degli altri, funzionerà solo su due file:

$ 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'

E se salvi il comando perl come alias, puoi ottenere:

$ 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. Come comprimere più file su Linux

  2. Ottenere tutti i file che sono stati modificati in una data specifica?

  3. Trovare file per i quali più varianti su quel nome file esistono insieme nella stessa directory?

  4. File di registro di Linux

  5. 20 File di registro Linux che si trovano nella directory /var/log

Come unire più file PDF in un unico PDF in Linux

Come unire/unire più file audio in uno in Linux

10 fantastici esempi per la visualizzazione di enormi file di registro in Unix

3 metodi per visualizzare l'output di coda -f di più file di registro in un terminale

sintassi del file di configurazione logrotate:sono possibili più voci jolly?

Ordina i file di testo con più righe come una riga