トリッキー。 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
に置き換えることで、連続するタイムスタンプ間のすべての行を 1 行にまとめただけです。 (これがログ ファイルにある可能性がある場合は、絶対に存在しないことがわかっている任意の文字列を使用してください)。これは sort
に渡されました そして tr
セリフを取り戻すために。
OPによって非常に正しく指摘されているように、上記のソリューションはすべて再利用する必要があり、ファイルをマージできることを考慮に入れていません。これは 1 つですが、他のものとは異なり、2 つのファイルでしか機能しません:
$ 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'