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'