Внешне кажется очевидным применение для sort
и join
:
sort -k2 file1 > sorted.1
sort -k1 file2 > sorted.2
join -1 2 -2 1 -a 2 -e '*' \
-o 2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,2.10,1.1,1.3,1.5 \
sorted.1 sorted.2
Однако, вывод из этого:
128.3.44.112 pay-per-view 148.184.171.6 netbios-ssn 0 0 3 186 3 186 * * *
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186 8 2122 80
128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 8 2122 80
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186 9 2123 22
128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 9 2123 22
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186 10 2124 80
128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 10 2124 80
128.3.45.12 cadabra-lm 148.184.171.6 microsoft-ds 0 0 3 186 3 186 * * *
Закрыть, но без кубика: проблема в том, что IP-адрес 128.3.45.10 трижды появляется в файле1 и дважды в файле2, а join
создает 6 строк (декартово произведение).
Это приложение, которое должно использовать / уничтожать записи по мере их использования. Это говорит о том, что нам нужно будет использовать Perl (или аналогичный язык сценариев). Тогда не ясно, что нам нужно отсортировать file1; нам нужно прочитать file1 и создать структуру с хеш-кодом на IP-адресе (поле 2), где ключ указывает на массив строк, каждая запись содержит только три поля (1, 3, 5), которые необходимы.
Затем мы последовательно обрабатываем файл2, находя соответствующий IP-адрес в хэше и используя первую запись в массиве - или звездочки, если такой записи нет. Мы также можем добавить '-->
', запрошенный в вопросе.
Это приводит к довольно простой программе:
#!/usr/bin/env perl
use strict;
use warnings;
my %file1 = read_file1("file1");
sub read_file1
{
my($file) = @_;
open my $fh, '<', $file or die "Failed to open $file for reading ($!)";
my %file1;
while (my $line = <$fh>)
{
my @fields = split / /, $line;
my $ip = $fields[1];
$file1{$ip} = [ ] unless defined $file1{$ip};
push @{$file1{$ip}}, "$fields[0] $fields[2] $fields[4]";
}
return %file1;
}
my $file2 = "file2";
open my $f2, '<', $file2 or die "Failed to open $file2 for reading ($!)";
while (my $line = <$f2>)
{
chomp $line;
my($ip) = ($line =~ m/^(\S+) /);
my $aux = "* * *";
if (defined $file1{$ip})
{
$aux = shift @{$file1{$ip}};
delete $file1{$ip} if scalar @{$file1{$ip}} == 0;
}
print "$line --> $aux\n";
}
И вывод такой - именно так, как запрошено:
128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 --> 8 2122 80
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186 --> 9 2123 22
128.3.44.112 pay-per-view 148.184.171.6 netbios-ssn 0 0 3 186 3 186 --> * * *
128.3.45.12 cadabra-lm 148.184.171.6 microsoft-ds 0 0 3 186 3 186 --> * * *
В поле зрения нет ни одного вида, поэтому он достаточно эффективен.