从日志文件中提取IP

时间:2015-12-03 23:22:24

标签: perl

我正在编写从日志文件中提取所有IP地址的代码。 (日志文件包含域名,IP地址和MAC地址列表。)这是我的代码:

npm install --only=prod

问题是每个IP地址打印5次。输出如下:

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;

问题出在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 ... ,还是在其他地方?

4 个答案:

答案 0 :(得分: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";
}

答案 1 :(得分:0)

不太确定为什么使用数组(@ip)来存储标量,输出(没有尾随,)与您的脚本不匹配,但是它多次出现的原因很可能是因为它在日志文件中多次出现。

如果您想跳过同一地址的连续出现,您需要记住上次看到的地址,而不是显示与上次看到的IP地址相匹配的任何IP地址。

如果您只想显示任何一个IP地址,则需要将所有地址存储在哈希(作为键)中,然后枚举哈希的键。或者只是使用哈希来记住你已经看过(并打印过)的IP。

答案 2 :(得分: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

答案 3 :(得分:-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;
相关问题