次の形式のログファイルを使用しています。
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