2015-12-03 5 views
0

Я пишу код, который извлекает все IP-адреса из файла журнала. (. Файл журнала содержит список доменных имен, IP-адресов и MAC-адресов) Вот мой код:Извлечь IP из файла журнала

open(CONF, '<', 'dhcpd.conf') or die "\n"; 
my @ip; 

while(my $line = <CONF>) { 
    if ($line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) { 
     @ip = $1; 
    } 

    print "@ip,\n"; 
} 

close CONF; 

Проблема заключается в том, что каждый IP-адрес печати 5 раз. Вывод выглядит следующим образом:

10.0.0.158 
10.0.0.158 
10.0.0.158 
10.0.0.158 
10.0.0.158 
10.0.0.159 
10.0.0.159 
10.0.0.159 
10.0.0.159 
10.0.0.159 
... 

ли проблема в @ip = $1, или это где-то еще?

ответ

2

У вас есть несколько проблем, но главное, похоже, что вы печатаете содержимое @ip независимо от того, соответствует ли строка. Если вы просто хотите использовать скрипт в качестве фильтра и IP печати адресов, как вы их найдете, это лучший способ выразить, что:

perl -ne 'print "$1\n" if /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/' dhcpd.conf 

Или эквивалентный код, который не один вкладыш:

use strict; 
use warnings; 

while (<>) { 
    next unless /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/; 
    print "$1\n";  
} 

Какой бы вы работать так:

$ perl script.pl dhcpd.conf 

Если вы хотите сохранить каждый IP-адрес, который вы найти и сделать что-то с ними позже, вы push на массив:

my @ips; 

while (<>) { 
    next unless /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/; 
    push(@ips, $1); 
} 

# doing something else... 

for (@ips) { 
    print "$_\n"; 
} 

Если вы хотите только уникальный IP-адрес по всему файлу, вы бы использовать hash:

my %ips; 

while (<>) { 
    next unless /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/; 
    $ips{$1} = 1; 
} 

for (keys(%ips)) { 
    print "$_\n"; 
} 
0

Не совсем уверен, почему вы используете массив (@ip) для хранения скаляра, а вывод (без трейлинга ,) не соответствует вашему сценарию, но причина, по которой он появляется несколько раз, скорее всего, потому что он выглядит несколько раза в файле журнала.

Если вы хотите пропустить последовательные появления одного и того же адреса, вам необходимо запомнить последний, который был замечен, и не отображать IP-адрес, соответствующий последнему.

Если вы хотите показывать только один IP-адрес один раз, вам необходимо сохранить все адреса в хеше (как ключи), а затем перечислить ключи хеша. Или просто используйте хеш для запоминания IP-адресов, которые вы уже видели (и распечатали).

0

Это, вероятно, потому, что этот IP-адрес показывает больше, чем когда-то в журнале, так что, как ожидается.

Если вы делали это из командной строки для скажем, стандартный Apache журнала вы получите аналогичный вывод с:

cat log | awk '{print $1}' | sort | sort -nr -k 1 | head 

Это не совсем аккуратно, но и для демонстрационных целей, вы можете затем использовали Uniq в между сортировками для удаления дубликатов. Вам нужно будет сделать что-то подобное в своем.

Существует модуль https://metacpan.org/pod/List::MoreUtils, который будет делать это легко:

use List::MoreUtils qw(uniq); 

my @ip = qw(ip1 ip2 ip3); 
my @ip = uniq @ip; 

Если вы не хотите использовать этот модуль, вы можете создать суб как:

sub uniq { 
    my %seen; 
    grep !$seen{$_}++, @_; 
} 

my @ip = qw(ip1 ip2 ip3); 
my @ip = uniq(@ip); 

См perlfaq4 для больше информации об этих методах.

-1

использование Hash вместо Array, попробуйте ниже код:

my $ips; 
open(CONF, '<', 'dhcpd.conf') or die "Error: $!"; 
while(my $line = <CONF>) { 
    if ($line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) { 
     $ips->{$1} = 1; 
    } 
} 
close CONF; 
my $all_ips =join("\n", keys %{$ips}); 
print $all_ips; 
+0

'присоединиться()' возвращает строку, а не список. –

Смежные вопросы