Tricky. Хотя это возможно с использованием массивов date
и bash, это действительно та вещь, которая выиграет от реального языка программирования. В Perl например:
$ 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
Вот то же самое, что не содержится в комментируемом скрипте:
#!/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}";
}
Обратите внимание, что это предполагает, что все строки даты и только строки даты содержат запятую. Если это не так, вы можете использовать это вместо:
perl -ne '$d=$1 if /^(\d+:\d+:\d+\.\d+),/; $k{$d}.=$_; END{print $k{$_} for sort keys(%k);}' log*
Приведенный выше подход должен сохранять все содержимое файлов в памяти. Если это проблема, вот та, которая этого не делает:
$ 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
Этот просто помещает все строки между последовательными временными метками в одну строку, заменяя символы новой строки на \0
(если это может быть в ваших файлах журнала, используйте любую последовательность символов, которую вы знаете, никогда не будет). Это передается для sort
а затем tr
чтобы вернуть строки.
Как очень правильно указал OP, все вышеперечисленные решения должны быть восстановлены и не принимать во внимание, что файлы могут быть объединены. Вот тот, который делает, но который в отличие от других будет работать только на двух файлах:
$ 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'
И если вы сохраните команду perl как псевдоним, вы можете получить:
$ 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'