Как эффективно сортировать IP-адреса и объединять два файла с помощью команд perl или * nix? - PullRequest
0 голосов
/ 29 декабря 2010

(*) Эта проблема должна быть решена в perl или любых * nix командах.

Я работаю над программой, и вопросы эффективности. Файл1 состоит из IP-адресов и некоторых других данных:

index ipsrc     portsrc  ip dest     port src
8 128.3.45.10 2122 169.182.111.161 80 (same ip src and dst)
9 128.3.45.10 2123 169.182.111.161 22 (same ip src and dst)
10 128.3.45.10 2124 169.182.111.161 80 (same ip src and dst)
19 128.3.45.128 62256 207.245.43.126 80

и других файлов2 выглядят так (файл1 и файл2 находятся в разном порядке)

128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186
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

1 - файл SORT1 с использованием IP-адреса во втором столбце и файл SORT2 с использованием IP-адреса в первом столбце

2 - объединение 1-го, 3-го и 5-го столбцов File1 с файлом 2

Мне нужно создать новый файл, который будет выглядеть так:

128.3.45.10 ioc-sea-lm 169.182.111.161 microsoft-ds 0 0 3 186 3 186 --> 2122 80 8
128.3.45.10 hypercube-lm 169.182.111.161 https 0 0 3 186 3 186 --> 2123 22 9
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 --> * * *

В основном будут добавлены номера портов и номера индекса.

1 Ответ

1 голос
/ 30 декабря 2010

Внешне кажется очевидным применение для 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 --> * * *

В поле зрения нет ни одного вида, поэтому он достаточно эффективен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...