다음과 같은 입력이 있습니다.
Sep 23 13:43 192.168.6.200
Sep 23 13:44 192.168.6.166
Sep 23 13:45 192.168.6.200
Sep 23 13:46 192.168.6.166
Sep 23 13:47 192.168.6.200
Sep 23 13:48 192.168.6.166
Sep 23 13:49 192.168.6.176
Sep 23 13:49 192.168.6.200
Sep 23 13:50 192.168.6.166
Sep 23 13:51 192.168.6.176
Sep 23 13:51 192.168.6.200
Sep 23 13:52 192.168.6.166
Sep 23 13:54 192.168.6.166
Sep 23 13:54 192.168.6.176
Sep 23 13:56 192.168.6.176
Sep 23 13:57 192.168.6.166
다음 출력이 필요합니다.
Sep 23 13:43 192.168.6.200
Sep 23 13:51 192.168.6.200
Sep 23 13:44 192.168.6.166
Sep 23 13:57 192.168.6.166
Sep 23 13:49 192.168.6.176
Sep 23 13:56 192.168.6.176
그래서 제가 생성한 OpenWrt 라우터의 DHCP 로그가 있습니다. (저는 "5m"의 dhcp 임대로 dhcp 서버를 구성했습니다):
logread | fgrep DHCPACK | awk '{print $1" "$2" "$3" "$8}' | sed 's/:[0-9][0-9] / /g' | sort -u
그런데 언급해야 할 입력이 언급된 출력인데 어떻게 해야 합니까? Perl 전문가가 있나요? :\ :디
답변1
awk는 (최대) fgrep 및 sed의 상위 집합이므로 세 가지를 모두 호출할 필요가 없습니다.
logread | awk '
/DHCPACK/ {
sub(/:..$/,"",$3)
t = $1 " " $2 " " $3
if (!($8 in first)) first[$8] = t
last[$8] = t
}
END {
for (i in first) {
print first[i], i
print last[i], i
print ""
}
}'
특별한 순서로 나타나지는 않지만. IP 주소가 로그에 처음 나타나는 순서대로 나타나도록 하려면 다음과 같이 변경할 수 있습니다.
logread | awk '
/DHCPACK/ {
sub(/:..$/,"",$3)
t = $1 " " $2 " " $3
if (!($8 in first)) {
first[$8] = t
ip[n++] = $8
}
last[$8] = t
}
END {
for (i = 0; i < n; i++) {
print first[ip[i]], i
print last[ip[i]], i
print ""
}
}'
답변2
빠른 해킹:
for ip in $(cut -d" " -f 4 < INPUT_FILE.txt | sort -u); do
grep "$ip" INPUT_FILE.txt | head -n1
grep "$ip" INPUT_FILE.txt | tail -n1
echo
done
그러나 로그 파일을 3번 반복하므로 속도가 그리 빠르지는 않습니다. 그리고 출력은 귀하의 예와 다른 순서로 되어 있습니다. 그것이 귀하에게 중요한지 잘 모르겠습니다.
답변3
주석이 달린 Perl 버전.
#! /usr/bin/perl
use strict;
use Date::Parse;
use Date::Format;
my $format = '%b %d %R';
my %IP=();
# read the input file, convert date/time to a time_t timestamp,
# and store it into a hash of arrays (HoA) 'man perldsc' for details
while(<>) {
chomp;
my($month, $day, $time, $ip) = split ;
my $time_t = str2time("$month $day $time");
push @{ $IP{$ip} }, $time_t;
};
# NOTE: hashes are inherently unsorted. replace "keys %IP" below
# with an IP sort function if you need the IPs sorted - e.g.
# http://www.perlmonks.org/?node_id=37889
# print the first and last time stamp seen, converting
# back to the same time format as the input.
foreach my $key (keys %IP) {
# sort the array held in $IP{$key} just in case the input
# lines are out of order
sort @{ $IP{$key} } ;
my $first = $IP{$key}[0];
my $last = $IP{$key}[scalar @{ $IP{$key} }-1];
# print the first and last time seen
# note: if an IP was seen only once, first and last will be the same.
# easy enough to add an if or unless here if you want to exclude
# IPs where first == last.
print time2str($format,$first) . " $key\n";
print time2str($format,$last) . " $key\n\n";
}
grep, awk 및 sed 이후에 로그를 파이핑하는 대신 원시 로그를 이 로그로 파이핑하려면 다음과 같이 변경하십시오.
- 다음
while(<>) {
으로 추가하세요.next unless /DHCPACK/;
줄을
split
다음으로 변경합니다.my ($month,$day,$year,undef,undef,undef,undef,$IP) = split;
답변4
가설크레이그정확하고 입력이 시간순으로 되어 있으면 awk
다음 관용적 스크립트를 사용할 수 있습니다.
파싱.awk
!start[$4] { start[$4] = $1" "$2" "$3 }
{ end[$4] = $1" "$2" "$3 }
END {
for (ip in start)
print start[ip], ip, "\n" end[ip], ip, "\n"
}
다음과 같이 실행하세요:
logread | awk -f parse.awk
산출:
Sep 23 13:43 192.168.6.200
Sep 23 13:51 192.168.6.200
Sep 23 13:44 192.168.6.166
Sep 23 13:57 192.168.6.166
Sep 23 13:49 192.168.6.176
Sep 23 13:56 192.168.6.176