【问题标题】:check if a pattern exist in a file检查文件中是否存在模式
【发布时间】:2013-06-13 13:39:24
【问题描述】:

我有一个关于模式匹配问题的非常简单的 perl 问题。 我正在阅读带有名称列表的文件(fileA)。 我想检查这些名称中的任何一个是否存在于另一个文件 (fileB) 中。

if ($name -e $fileB){
    do something
}else{
    do something else
}

这是一种检查文件中是否存在模式的方法。 我试过了

open(IN, $controls) or die "Can't open the control file\n";
    while(my $line = <IN>){
            if ($name =~ $line ){
                    print "$name\tfound\n";
            }else{
                    print "$name\tnotFound\n";
            }
    }

当它检查并打印每个条目而不是检查名称是否存在时,这会重复自己。

【问题讨论】:

  • -e 是一个文件测试,它检查某个文件是否存在。它与文件的内容没有任何关系。
  • 在这里称它为模式匹配有点误导,你匹配的是精确的字符串,不是吗?模式意味着有一些通配符或正则表达式在起作用。

标签: perl pattern-matching


【解决方案1】:

要检查文件中是否存在模式,您必须打开文件并读取其内容。搜索包含两个列表的最快方法是将内容存储在哈希中:

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

open my $LST, '<', 'fileA' or die "fileA: $!\n";
open my $FB,  '<', 'fileB' or die "fileB: $!\n";

my %hash;
while (<$FB>) {
    chomp;
    undef $hash{$_};
}

while (<$LST>) {
    chomp;
    if (exists $hash{$_}) {
        print "$_ exists in fileB.\n";
    }
}

【讨论】:

    【解决方案2】:

    当您将一个列表与另一个列表进行比较时,您会对哈希感兴趣。散列是一个键控数组,列表本身没有顺序。一个哈希只能有一个特定键的实例(但不同的键可以有相同的数据)。

    您可以做的是浏览第一个文件,并创建一个以该行为键的哈希。然后,您浏览第二个文件夹并检查这些行是否与哈希中的任何键匹配:

    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    use feature qw(say);
    use autodie;  #You don't have to check if "open" fails.
    
    use constant {
        FIRST_FILE   => 'file1.txt',
        SECOND_FILE  => 'file2.txt',
    };
    open my $first_fh, "<", FIRST_FILE;
    
    # Get each line as a hash key
    my %line_hash;
    while ( my $line = <$first_fh> ) {
        chomp $line;
        $line_hash{$line} = 1;
    }
    close $first_fh;
    

    现在每一行都是哈希%line_hash 中的一个键。数据真的无所谓。重要的部分是密钥本身的值。

    现在我有了第一个文件中行的哈希值,我可以读取第二个文件并查看该行是否存在于我的哈希中:

    open my $second_fh, "<", SECOND_FILE;
    while ( my $line = <$second_fh> ) {
        chomp $line;
        if ( exists $line_hash{$line} ) {
            say qq(I found "$line" in both files);
        }
    }
    close $second_fh;
    

    还有一个map 函数可以使用:

    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    use feature qw(say);
    use autodie;  #You don't have to check if "open" fails.
    
    use constant {
        FIRST_FILE   => 'file1.txt',
        SECOND_FILE  => 'file2.txt',
    };
    open my $first_fh, "<", FIRST_FILE
    chomp ( my @lines = <$first_fh> );
    
    # Get each line as a hash key
    my %line_hash = map { $_ => 1 } @lines;
    close $first_fh;
    
    open my $second_fh, "<", SECOND_FILE;
    while ( my $line = <$second_fh> ) {
        chomp $line;
        if ( exists $line_hash{$line} ) {
            say qq(I found "$line" in both files);
        }
    }
    close $second_fh;
    

    我不是map 的忠实粉丝,因为我发现它的效率并没有那么高,而且更难理解发生了什么。

    【讨论】:

      【解决方案3】:

      我刚刚给出了一种未经测试的算法代码。 但我觉得这对你有用。

      my @a;
      my $matched
      my $line;
      open(A,"fileA");
      open(A,"fileB");
      while(<A>)
      {
          chomp;
          push @a,$_;
      }
      while(<B>)
      {
          chomp;
          $line=$_;
          $matched=0;
          for(@a){if($line=~/$_/){last;$matched=1}}
          if($matched)
          {
              do something
          }
          else
          {
              do something else
          }
      }
      

      【讨论】:

      • 你正在做一个双循环,它将花费 O2 的时间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      相关资源
      最近更新 更多