如何匹配超出范围的数字

时间:2014-07-27 12:29:00

标签: perl

我正在尝试从@ arr3打印范围值,它们是相同的并且位于@ arr4范围之外(不包括在arr4的范围内)但是我没有得到所需的输出。请在下面的代码中建议修改以获得1,2,8,13的输出(如果有的话,不重复值)

文件1:结果

1..5   
5..10
10..15 

文件2:注释

3..7
9..12
14..17

代码:

#!/usr/bin/perl

open($inp1, "<result")     or die "not found";
open($inp2, "<annotation") or die "not found";

my @arr3 = <$inp1>;
my @arr4 = <$inp2>;

foreach my $line1 (@arr4) {
  foreach my $line2 (@arr3) {

    my ($from1, $to1) = split(/\.\./, $line1);
    my ($from2, $to2) = split(/\.\./, $line2);

    for (my $i = $from1 ; $i <= $to1 ; $i++) {
      for (my $j = $from2 ; $j <= $to2 ; $j++) {

        $res = grep(/$i/, @result);    #to avoid repetition

        if ($i != $j && $res == 0) {

          print "$i \n";

          push(@result, $i);
        }
      }
    }
  }
}

3 个答案:

答案 0 :(得分:1)

试试这个:

#!/usr/bin/perl
use strict;
open (my $inp1,"<result.txt") or die "not found";
open (my $inp2,"<annotation.txt") or die "not found";

my @result;
my @annotation;

foreach my $line2 (<$inp2>) {
    my ($from2,$to2)=split(/\.\./,$line2);
    @annotation = (@annotation, $from2..$to2);
}
print join(",",@annotation),"\n";
my %in_range = map {$_=> 1} @annotation;

foreach my $line1 (<$inp1>) {
    my ($from1,$to1)=split(/\.\./,$line1);
    @result = (@result, $from1..$to1);
}

print join(",",@result),"\n";
my %tmp_hash = map {$_=> 1} @result;
my @unique = sort {$a <=> $b} keys %tmp_hash;
print join(",",@unique),"\n";

my @out_of_range = grep {!$in_range{$_}} @unique;
print join(",",@out_of_range),"\n";

print语句当然是临时的,以帮助显示运行此命令时发生的情况。基本思路是使用一个哈希来消除“结果”中的重复数字,另一个哈希表示哪些是在“注释”中。

如果您使用了模式匹配而不是split,那么我认为如果您输入的文件中包含一个数字,则忽略额外的输入行会更容易一些您需要跳过的“额外”行很少。

答案 1 :(得分:1)

如果文件内容在您的控制之下,您可以使用eval进行解析。另一方面,如果可能存在您指定的内容,则以下内容使用起来很危险。

#!/usr/bin/perl

use strict;
use warnings;
use autodie;
use Data::Dumper;

open my $inc, '<', 'result';
open my $exc, '<', 'annotation';

my (%include, %exclude, @result);
while (<$inc>) { $include{$_} = 1 for eval $_ }
while (<$exc>) { $exclude{$_} = 1 for eval $_ }

for (sort {$a <=> $b} keys %include) {
    push @result, $_ unless $exclude{$_}
}
print Dumper \@result;

返回:

$VAR1 = [ 1, 2, 8, 13 ];

答案 2 :(得分:0)

您需要的唯一主要工具是%seen

中表示的use strict; use warnings; use autodie; my %seen; open my $fh_fltr, '<', \ "3..7\n9..12\n14..17\n"; while (<$fh_fltr>) { my ($from, $to) = split /\.{2}/; $seen{$_}++ for $from .. $to; } my @result; open my $fh_src, '<', \ "1..5\n5..10\n10..15\n"; while (<$fh_src>) { my ($from, $to) = split /\.{2}/; push @result, $_ for grep {!$seen{$_}++} $from .. $to; } print "@result\n"; 样式哈希

以下打开文件句柄到字符串引用,但显然可以用适当的文件名替换它们:

1 2 8 13

输出:

{{1}}