【问题标题】:Comparison of a set of strings and a file using Perl使用 Perl 比较一组字符串和一个文件
【发布时间】:2014-08-15 02:57:09
【问题描述】:

我正在尝试编写一个 Perl 脚本来找出一组字符串和一个文件之间的区别,并且我想打印与字符串不匹配的文件的内容。

我的 INPUT1 会是:(字符串集)

AAAAA
BBBBB
CCCCC
DDDDD
EEEEE   --- These are user ids which should be passed in the script

我的 INPUT2 将是一个 User.txt 文件,其中包含许多 id,包括上面提到的那些

ABBAAA
ACARVAV
AAAAA
BBBBB
CCCCC
DDDDD
EEEEE
BGATA
ETYUIOL

我希望我的输出像

ABBAAA
ACARVAV
BGATA
ETYUIOL

到目前为止,我已经到了

my @things_to_find = qw(AAAAAA BBBBB CCCCC DDDDD EEEEE);
my $comparefile = "User.txt";
open ( my $compare_filehandle, "<", $comparefile ) or die $!;
while ( my $line = <$compare_filehandle> ) 
{
    foreach my $thing ( @things_to_find )
    {
        print "Match found with: $line" if $line !~ /$thing/;
    }
}

但这并没有产生所需的输出。我对 Perl 很陌生,所以您的任何建议都会对我很有帮助。

【问题讨论】:

    标签: arrays regex perl


    【解决方案1】:

    试一试:

    use List::Util qw(none);
    my @things_to_find = qw(AAAAAA BBBBB CCCCC DDDDD EEEEE);
    my $comparefile = "User.txt";
    open ( my $compare_filehandle, "<", $comparefile ) or die $!;
    while ( my $line = <$compare_filehandle> ) 
    {
        print $line if none { $line =~ /\b$_\b/}  @things_to_find;
    }
    

    文档List::Util

    【讨论】:

    • 如果文件中有BBBBBC怎么办?
    • @RobEarl:很好,已修复。
    【解决方案2】:

    就目前而言,您自己的代码会在文件中找到所有不包含所有列表中字符串的行,而它应该是不等于任何 em> 这些字符串。您需要将包含测试更改为相等测试;找到匹配项后立即跳过字符串;并使用chomp 删除从文件读取的字符串中的尾随换行符。

    有两种明显的写法。首先是构建一个hash,它实际上是一个由字符串而不是整数索引的数组。如果您用文件中的条目填充哈希,然后删除字符串数组中的条目。应该是这样的

    use strict;
    use warnings;
    
    my $comparefile = 'User.txt';
    my @users = qw/ AAAAA BBBBB CCCCC DDDDD EEEEE /;
    
    open my $users_fh, '<', $comparefile or die $!;
    
    my %file_users;
    while (my $user = <$users_fh> ) {
      chomp $user;
      $file_users{$user} = 1;
    }
    
    delete $file_users{$_} for @users;
    
    print "$_\n" for sort keys %file_users;
    

    输出

    ABBAAA
    ACARVAV
    BGATA
    ETYUIOL
    

    另一种方法是从字符串构建一个正则表达式,并使用它从文件中选择那些要被忽略的行。这看起来像下面的程序,并且输出与前一个程序的输出相同。此解决方案会更快,但包含一些更高级的想法,例如正则表达式和map,因此您可能更喜欢第一个。

    use strict;
    use warnings;
    
    my $comparefile = 'User.txt';
    my @users = qw/ AAAAA BBBBB CCCCC DDDDD EEEEE /;
    
    my $re = join '|', map "^\Q$_\E\$", @users;
    $re = qr/$re/;
    
    open my $users_fh, '<', $comparefile or die $!;
    
    my @file_users;
    while (my $user = <$users_fh> ) {
      chomp $user;
      push @file_users, $user unless $user =~ $re;
    }
    
    print "$_\n" for sort @file_users;
    

    【讨论】:

      【解决方案3】:

      你可以试试这个简单的grep 匹配模式。

      use strict;
      use warnings;
      use autodie;
      
      my @users = qw(AAAAAA BBBBB CCCCC DDDDD EEEEE);
      
      my $file = "User.txt";
      open my $fh, "<", $file;
      while ( my $line = <$fh> ) {
          chomp $line;
          print "Matched line : $line\n" unless grep {$line eq $_} @users;
      }
      

      注意:
      对于搜索模式,使用 grepmap 优于 foreachfor

      【讨论】:

        【解决方案4】:
        use strict;
        use warnings;
        use autodie;
        
        open my $in, '<', 'in.txt'; 
        open my $in2, '<', 'in_2.txt';
        
        my (%data1, %data2);
        while(<$in>){
            chomp;
            $data1{$_} = 1;
        }
        
        while(<$in2>){
            chomp;
            $data2{$_} = 2;
        }
        
        
        foreach(sort keys %data2){
            print "$_\n" unless $data1{$_};
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-31
          • 2016-06-16
          • 2014-06-11
          • 2015-03-14
          • 1970-01-01
          • 2012-03-23
          • 2021-03-16
          • 1970-01-01
          相关资源
          最近更新 更多