Perl Regex帮助 - 在另一个文件中查找行

时间:2015-04-29 11:48:12

标签: regex perl

我希望比赛能够发生,但事情并没有发生。

我有一个问题。我希望在另一个文件中找到行的出现。

这是一个文件(@file)

735 1 1  
1891 1 0  
2021 1 1  
1892 2 1  
667 1 0  
802 2 1  
665 1 0  
666 1 1  
596 1 0  
3193 2 1  

这是我必须在上面找到的行(@ file1)

1521 1 0 : 1167 0 0 : 1167 2 0 : 1167 1 0 ;  
2605 1 1 ;  
2280 0 1 : 2280 2 0 : 1892 0 0 : 2280 1 0 : 2021 0 0 ;  
1892 2 1 : 667 0 1 : 667 1 0 ;  
1892 1 1 ;  

这是我写的代码

foreach $leadline (@file1) {

  foreach $line (@file) {
    $_    = ' ' . $leadline;
    $line = ' ' . $line;
    if (m/$line/) {
      push @final, $_;
    }

  }

}

但我无法检测到这些线条。

@file1@file变量存储文件的内容。

我要么没有检测到线路,要么检测到所有线路。

我在两行之前连接空格的原因是,有时667 1 0可以作为给定行中的第一个短语出现。我不熟悉Regex直接在Regex中执行此操作。

注意: - 如果第一个文件中的第i行和第j行作为另一个文件的同一行中的模式出现,则输出应该只是其中一行。此外,如果找到模式1667 1 0,则不应将其与667 1 0混淆。因此,我添加了空格。

我能够在Python中实现这一目标,但无法在Perl中复制它。这是Python片段: -

for line1 in file1:
    for j in range(0,len(file0)-1):# in file0:
        if ' '+lines[j][0:len(file0[j])-1] in ' '+line1:
            i = i + 1
            print line1[0:len(line1)-1]
            break  

预期产量为: - 1892 2 1:667 0 1:667 1 0;

3 个答案:

答案 0 :(得分:1)

您可以通过|加入来自file1的行(并在每个上应用quotemeta)来创建正则表达式。 \b应阻止667中的1667匹配。

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

my @search;
open my $F1, '<', 'file1' or die $!;
while (<$F1>) {
    chomp;
    push @search, quotemeta;
}

my $regex = join '|', @search;
$regex = qr/\b(?:$regex)\b/;

open my $F2, '<', 'file2' or die $!;
while (<$F2>) {
    print if /$regex/;
}

答案 1 :(得分:1)

我现在认为这是解决另一个问题的方法,但无论如何它都在这里!

use warnings;
use strict;
use 5.010;

use Array::Utils 'array_diff';

open my $fh, '<', 'f1.txt' or die $!;
my @f1;
while ( <$fh> ) {
  push @f1, [split];
}

my @final;
open $fh, '<', 'f2.txt' or die $!;
while ( <$fh> ) {
  my @f2 = map [ /\d+/g ], split /:/;
  for my $f1 ( @f1 ) {
    my @matches = grep { not array_diff(@$f1, @$_) } @f2;
    push @final, map "@$_", @matches;
  }
}

say for @final;

<强>输出

1892 2 1
667 0 1
667 1 0

<强>更新

好的,这是我的第二次尝试!这基本上是choroba wrote,但是使用map并且在第一个文件的数据上添加了剥离所有尾随空格。

use warnings;
use strict;
use 5.014;  # For non-destructive substitution

open my $fh, '<', 'f1.txt' or die $!;
my @f1 = map s/\s+\z//r, <$fh>;
my $re = join '|', @f1;

open $fh, '<', 'f2.txt' or die $!;
my @final = grep /\b(?:$re)\b/, <$fh>;

print for @final;

<强>输出

1892 2 1 : 667 0 1 : 667 1 0 ;  

答案 2 :(得分:1)

以下是我的工作方式:

use Modern::Perl;
use Data::Dumper;$Data::Dumper::Indent = 1;

my @file = (
'735 1 1',
'1891 1 0',
'2021 1 1',
'1892 2 1',
'667 1 0',
'802 2 1',
'665 1 0',
'666 1 1',
'596 1 0',
'3193 2 1',
);
my @final;
while(my $line = <DATA>) {
    chomp $line;
    if (grep{$line =~ /\b$_\b/} @file) {
        push @final, $line;
    }
}
say Dumper\@final;

__DATA__
1521 1 0 : 1167 0 0 : 1167 2 0 : 1167 1 0 ;  
2605 1 1 ;  
2280 0 1 : 2280 2 0 : 1892 0 0 : 2280 1 0 : 2021 0 0 ;  
1892 2 1 : 667 0 1 : 667 1 0 ;  
1892 1 1 ;  

<强>输出:

$VAR1 = [
  '1892 2 1 : 667 0 1 : 667 1 0 ;  '
];

使用您的文件:

use Modern::Perl;
use Data::Dumper;$Data::Dumper::Indent = 1;

open my $fh, '<', 'file.txt' or die "unable to open 'file.txt': $!";
my @file = <$fh>;
chomp @file;

my @final;
open $fh, '<', 'file1.txt' or die "unable to open 'file1.txt': $!";
while(my $line = <$fh>) {
    chomp $line;
    if (grep{$line =~ /\b$_\b/} @file) {
        push @final, $line;
    }
}
say Dumper\@final;