日付/時刻に基づいてログファイルの最後の一意の行のみを印刷します。

日付/時刻に基づいてログファイルの最後の一意の行のみを印刷します。

次の形式のログファイルを使用しています。

Oct 12 01:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 01:30:00 server program: 192.168.1.104 text for 1.104 
Oct 12 01:30:23 server program: 192.168.1.103 text for 1.103
Oct 12 01:32:39 server program: 192.168.1.101 text for 1.101 
Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103 
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101 

私はこれを達成する必要があります:

Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101

新しい出力をファイルに送信するには?私はこれを試しました:

awk '!_[$6]++ {a=$6} END{print a}' logfile

しかし、期待した結果は出ません。 awk または sed を使用して最後に最後に文字列の一致を見た一意の行のみを提供したり、日付/時刻に基づいて行うにはどうすればよいですか?

答え1

2番目のパス(ほとんどが必要です)を実行する予定の場合は、レコード全体ではなく行番号のみを保存できます。ロジックをより簡単にします。

awk 'NR == FNR {if (z[$6]) y[z[$6]]; z[$6] = FNR; next} !(FNR in y)' logfile logfile

精度証明:

各行の処理が終了すると、これまでに処理された各行の数は次のようになります。誰でもzまたはのインデックス(値ではない)y(両方ではない)

z各反復が終了すると、値で表される行は、正確に各 IP アドレスについてこれまでに表示された最新のレコードです。

したがって、のインデックスはy正確に私たちが望む線です。いいえ印刷。

答え2

行全体($6配列インデックスとして使用)を保存し、END配列要素を繰り返します。

awk '{z[$6]=$0};END{for (i in z) print z[i]}' logfile

しかし、結果はソートされません。次のようにできます。

awk '{z[$6]=NR" "$0};END{for (i in z) print z[i]}' logfile | sort -k1,1n | cut -f2-
### this space ^ is a literal TAB

これにより、行番号が保存されます。行番号で並べ替えるには、行の内容を追加してください。


他の方法には、日付別に並べ替える2番目のステップがあります(ログなので)。ただし、入力に重複行(つまり行全体)が含まれている場合、重複項目が印刷されます。たとえば、次のようになりますgrep

awk '{z[$6]=$0};END{for (var in z) print z[var]}' logfile | grep -Fxf- logfile

または単にawk

awk 'NR==FNR{z[$6]=$0;next}
FNR==1{for (var in z) y[z[var]]}
$0 in y' logfile logfile

答え3

同じ日の行だけがある場合は、次のように処理できます。

sort -k6 -k3r logfile | uniq -f3 | sort -k3

キューが1日以上の場合でも、このデフォルトの方法を使用できますが、順序をより賢く指定する必要があります。上記のコマンドは、タイムスタンプの時間部分(たとえば02:28:26)をタイムスタンプ全体のプロキシとして使用するため、1日分のレコードのみを処理できます。

答え4

ファイルを1行ずつ反転すると、ロジックがより簡単になります。

$ tac logfile | awk '!seen[$6]++' | tac
Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103 
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101 

関連情報