将多个列表中的IP地址复制到一个列表中

时间:2014-08-18 23:19:01

标签: perl

我正在尝试从位于同一目录中的几个不同列表中创建一个IP地址列表。除IP地址外,每个列表还有其他文本和单词。我有以下代码:

#!/usr/bin/perl
use strict;
use warnings;

my $dir = "/home/RHart1/blacklists";

opendir(my $dh, $dir) or die "cannot open directory";
my @lists = grep(/(((\w+[-_]\w+){1,5})\.\w+)$/,readdir($dh));

foreach my $file (@lists) {
    open (LIST, "$file") or die $!;
    while (<LIST>) {
         open (OUTPUTLIST, '>>badguys.txt');
         if (/^(([0-9]{1,3}\.){3}[0-9]{1,3}($|\/([0-9]{1,2})))$/) {
               print OUTPUTLIST "$1\n";
         }
    close $file;
   }
}

close OUTPUTLIST;
closedir $dh;

但是,我在第11行遇到了问题。它说:

No such file or directory at ./testperl.pl line 11.

我在这里做错了什么?

感谢。

1 个答案:

答案 0 :(得分:3)

来自readdir的文档:

  

如果您计划对readdir之外的返回值进行文件测试,则最好先添加相关目录。否则,因为我们没有chdir,所以它会测试错误的文件。

因此,在打开文件时,请务必包含路径信息。

open (LIST, "$dir/$file") or die $!;

或者,您可以chdir到您正在阅读的目录。

使用现代Perl风格

我还建议您对代码进行一般性的现代化改造。

  • 使用autodie为文件操作获取更好的自动错误消息
  • 使用具有open
  • 的3参数形式的词法文件句柄

这两个和一些小修正将产生以下结果:

#!/usr/bin/perl
use strict;
use warnings;
use autodie;

my $dir = "/home/RHart1/blacklists";

open my $outfh, '>>', 'badguys.txt';

opendir my $dh, "$dir";
while ( my $file = readdir $dh ) {
    next unless $file =~ /(\w+[-_]\w+){1,5}\.\w+$/;

    open my $fh, '<', "$dir/$file";
    while (<$fh>) {
        if (/^(([0-9]{1,3}\.){3}[0-9]{1,3}($|\/([0-9]{1,2})))$/) {
            print $outfh "$1\n";
        }
    }
}

使用Path :: Class进行跨平台路径和文件操作

Perl核心附带File::Spec用于跨平台文件操作。它有效,但很尴尬。作为替代方案,有Path::Class可以为后端的核心库提供更清晰的界面。

需要安装,但以下是使用此cpan模块完成的脚本:

use strict;
use warnings;
use autodie;

use Path::Class;

my $dir = dir('', 'home', 'RHart1', 'blacklists');

open my $outfh, '>>', 'badguys.txt';

while (my $file = $dir->next) {
    next unless $file->basename =~ /(\w+[-_]\w+){1,5}\.\w+$/;

    my $fh = $file->openr();
    while (<$fh>) {
        if (/^(([0-9]{1,3}\.){3}[0-9]{1,3}($|\/([0-9]{1,2})))$/) {
            print $outfh "$1\n";
        }
    }
}