【问题标题】:Using Perl to match all words after a particular word使用 Perl 匹配特定单词之后的所有单词
【发布时间】:2015-07-24 02:57:57
【问题描述】:

我正在使用 Perl,需要将所有域名从 http://www.malwaredomainlist.com/hostslist/hosts.txt 获取到一个平面文件中。

我认为最简单的方法是使用正则表达式,但我不知道如何构建表达式。

到目前为止我的代码: #!/usr/bin/perl 使用 LWP::Simple;

$url = 'http://www.malwaredomainlist.com/hostslist/hosts.txt';

$content = get $url;
open(my $fh, '>', '/home/jay/feed.txt');
#logic here
}
close $fh;

我不确定是否应该遍历每一行并对其执行表达式,或者是否应该将整个文件作为字符串并使用它。

【问题讨论】:

  • 您应该始终发布一个简短但完整的脚本,而不是不工作的 sn-ps,以尽量减少其他人需要做的工作。
  • Sobrique 编写了一个解决方案,尝试从列表中的 主机名 中提取 域名,而 Sinan Ünür 和我假设您只需要文件中的第二列数据。请问哪个是正确的?我不清楚您的主题行如何匹配特定单词后的所有单词与您的描述相关
  • Borodin,我想获取 127.0.0.1 之后的所有内容,除了第一行 localhost。例如0koryu0.easter.ne.jp 109-204-26-16.netconnexion.managedbroadband.co.uk 11.lamarianella.info 等

标签: regex perl


【解决方案1】:

该页面只是一个text/plain 文档,所以我想我只需将该页面复制并粘贴到我的编辑器中并删除不需要的信息。但是,如果您更喜欢 Perl 程序,那么这就是所有必要的。它使用LWP::Simple::get 来获取文本页面和一个正则表达式来搜索以数字和点开头的行,返回每个的第二个字段

use strict;
use warnings;
use feature 'say';

use LWP::Simple qw/ get /;

my $url = 'http://www.malwaredomainlist.com/hostslist/hosts.txt';
say for get($url) =~ /^[\d.]+\s+(\S+)/gam;

或单线

perl -MLWP::Simple=get -E"say for get(shift) =~ /^[\d.]+\s+(\S+)/gam" http://www.malwaredomainlist.com/hostslist/hosts.txt

【讨论】:

  • 感谢正则表达式,但它似乎不起作用 - 你能帮我看看它有什么问题吗? regex101.com/r/kC3sA8/2
  • 您没有正确复制它。你需要修饰符/gam。你使用的是什么版本的 Perl?
  • V 5.18。我在修饰符部分输入了 /gam,但仍然不适合我
  • @Jamie:我不知道为什么它现在不起作用。在您的 regex101 上使用 /gm 没问题(它不会接受 /a
【解决方案2】:

除非您有特殊需要,否则按行迭代是前进的方向。否则你只会不必要地占用内存。

但是,当您获取 url 时,它有点学术性 - 我建议先将其获取到文件中并不是一件坏事,因此您可以重新处理它而无需重新获取。

给定源数据样本:

 for ( split ( "\n", $content ) ) {
      next unless m/^\d/; #skip lines that don't start with a digit. 
      my ( $IP, $hostname ) = split;
      my $domainname = $hostname =~ s/^\w+\.//r;
      print $domainname,"\n";
 }

但这并不完全适用于您的列表,因为在该列表中您有主机名和域名的混合,实际上并不那么容易区分。

毕竟,结尾的“tld”可能是.com,也可能是.org.it

【讨论】:

  • +1 但您的 split 不必要地增加了内存占用。最好使用 readline 逐行阅读字符串。
【解决方案3】:
127.0.0.1\s+(.*)

使用全局修饰符应该可以正常工作。

Demo

【讨论】:

    【解决方案4】:

    除非需要在本地保存列表文件(在这种情况下,最好只使用wgetcurl),否则无需将其保存在外部文件中以逐行处理 -行。

    您可以改为打开字符串本身的文件句柄。

    在下面的脚本中,extract_hosts 无论你给它一个字符串还是一个文件名的引用都一样:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use Carp qw( croak );
    use LWP::Simple qw( get );
    
    my $url = 'http://www.malwaredomainlist.com/hostslist/hosts.txt';
    
    my $malware_hosts = get $url;
    unless (defined $malware_hosts) {
        die "Failed to get content from '$url'\n";
    }
    
    my $hosts = extract_hosts(\$malware_hosts);
    print "$_\n" for @$hosts;
    
    sub extract_hosts {
        my $src = shift;
    
        open my $fh, '<', $src
            or croak "Failed to open '$src' for reading: $!";
    
        my @hosts;
    
        while (my $entry = <$fh>) {
            next unless $entry =~ /\S/;
            next if $entry =~ /^#/;
    
            my (undef, $host) = split ' ', $entry;
            push @hosts, $host;
        }
    
        close $fh
            or croak "Failed to close '$src': $!";
    
        \@hosts;
    }
    

    这将为您提供主机列表。

    【讨论】:

      【解决方案5】:

      用于 grep 给定文件中的主机名的代码。

      use LWP::Simple;
      my $url = 'http://www.malwaredomainlist.com/hostslist/hosts.txt';
      
      my $content = get $url;
      my @server_names = split(/127\.0\.0\.1\s*/, $content);
      
      open(my $fh, '>', '/home/jay/feed.txt');
      print $fh "@server_names";
      close $fh;
      

      【讨论】:

        【解决方案6】:

        这是另一个实现。它使用 HTML::Tiny,它是核心的一部分,因此您无需安装任何东西。

         use HTTP::Tiny;
        
         my $response = HTTP::Tiny->new->get('http://www.malwaredomainlist.com/hostslist/hosts.txt');
        
         die "Failed!\n" unless $response->{success};
         my @content;
        
         for my $line ( split ( "\n", $response->{content} ) ){
             next if ( $line =~ /^#|^$/);
             push @content, ((split ( " ", $line ))[1]);
          }
        
          print Dumper (\@content);
        

        【讨论】:

          猜你喜欢
          • 2012-11-16
          • 2020-03-09
          • 2019-04-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-21
          • 2022-01-21
          相关资源
          最近更新 更多