Вы могли бы использовать ОС, где zcat для сжатых файлов, в то время как gzcat для gzipped. В таком случае это должно работать:
ls -t ssl-access*.gz | xargs -n 1 gzcat
Править:
Я воспроизвел подобное, но не идентичное поведение на Солярисе:
$ ls -t1 *.gz | xargs -n 1 zcat
c.gz.Z: No such file or directory
b.gz.Z: No such file or directory
a.gz.Z: No such file or directory
На базирующемся распределении Debian (Ubuntu) я не воспроизвожу Вашу проблему.
Это могло бы работать так или иначе:
cat $(ls -t ssl-access*.gz) | zcat
или эквивалент:
zcat <(cat $(ls -t ssl-access*.gz))
или этот более простой, который избегает ненужной кошки
zcat $(ls -t ssl-access*.gz)
Ни один из них не обработает нечетные имена файлов как те со встроенными пробелами.
Быстрый взлом:
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 раза. И вывод не находится в том же порядке, имеет Ваш пример; я не уверен, важно ли это для Вас.
Обратите внимание, что 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 ""
}
}'
версия жемчуга, с комментариями.
#! /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;
Принятие Craig является правильным и что Ваш вход хронологически заказан, это идиоматичное awk
сценарий может использоваться:
parse.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