2012-06-01 151 views
0

给出下列文件:的Perl:数组的哈希值与另一个阵列相比

A. hash.pl:

%h1 = (
    A=>['4631 4576','6646 6646',], 
    B=>['3539 4576',], 
); 

B. input.txt中

4576 4631 4 
4576 3539 4 

我必须写在input.txt中查找值(4631 4576)的Perl代码。 (顺序不重要。)这里,'4631 4576'在input.txt中显示为4576 4631。

我写了下面的代码,但似乎有一些问题:

#!/usr/bin/perl -w 
open (FH, "input.txt") or die "can't open file: &! \n"; 
require "hash.pl"; 
foreach $amp (<FH>) 
{ 
    if ($amp=~/(\d+)\t(\d+)\t(\d+)/)   
    {  
     foreach $keys (keys %h1) 
     { 
      @tmparray= @{$h1{$keys}}; 
      foreach $tmp1 (@tmparray) 
      { 
       if ($tmp1 =~ m/($1 $2|$2 $1)/) 
       { 
        print "$keys", "$3\n"; 
       } 
      } 
     } 
    } 
} 
close (FH); 
exit; 

什么是错的代码?

+0

问题是什么? – ArjunShankar

回答

2

将该溶液优先于require使用do因为后者是用于inluding库源文件和在此上下文中返回一个无用标量值。 do简单地返回执行的最后一个语句的值,因此可以用于初始化一个局部变量。

而不是使用正则表达式,这个程序只是调用split收集文件中的非空白领域。然后检查是否有三个数字。

split的结果放入数组可避免捕获的正则表达式字段丢失的问题。

构建正则表达式$re,允许前两个字段以任意顺序出现,然后在每个散列元素上调用grep以验证散列值数组中的任何值是否与此文件条目匹配。

输出似乎微乎其微,但它包含了相同的信息显示原始代码。

use strict; 
use warnings; 

my %data = do 'hash.pl'; 

open my $fh, '<', 'input.txt' or die $!; 

while (<$fh>) { 

    my @values = split; 
    next if grep /\D/, @values or @values != 3; 

    my $re = qr/\A$values[0]\s+$values[1]\z|\A$values[1]\s+$values[0]\z/; 

    foreach my $key (keys %data) { 
    print "$key - $values[2]\n" if grep $_ =~ $re, @{$data{$key}}; 
    } 
} 

输出

A - 4 
B - 4 
0

您正试图在另一个正则表达式中重用变量$1,$2$3,我怀疑这是什么让事情变得糟糕。当我尝试你的代码,我得到的错误:

Use of uninitialized value $2 in regexp compilation ... 

因此,一个可行的办法是复制的价值,他们被捕获之后,为了避免$1等变量,成为覆盖当第二正则表达式编译:

if ($amp=~/(\d+)\t(\d+)\t(\d+)/) {  
    my @args = ($1,$2,$3); 

然后当然用$args[0]等取代$1等等。

你也应该知道,运行没有use warnings的脚本不是一个好主意。你认为你通过懒惰节省的时间在调试简单错误时会损失10倍。 Why use strict and warnings?

+1

或只是'如果(我的@args = $安培=〜/(\ d +)\吨(\ d +)\吨(\ d +)/)' – ysth

+0

除非你对数据文件中的质量问题,这也可以被写成'我@args =分裂',$ amp'。 – Borodin

1

的问题很简单:你在你的程序中使用$1$2,并且$3,但你使用它们的时候,你已经失去了其价值。这些是全局符号,只要使用正则表达式运算符就会被替换。在第一次正则表达式匹配后,将它们保存在另一个变量中:

$first = $1; 
$second = $2; 
$third = $3; 

您还应该小心正则表达式。你的正则表达式工作,但它们非常非常狭窄。我第一次在文件中加入标签时错过了它。我喜欢使用\s+来处理任何类型的空白。这将涵盖多个选项卡或空间或不同组合。

我也强烈建议你多学些modern Perl。你会立刻拿起这个问题,如果你已经在你的程序中使用这两条线:

use strict; 
use warnings; 

strict将确保您通过myour定义的变量。这确保你不会说$Foo一个地方和$foo另一个地方,并想知道你在$foo存储的价值发生了什么。

warnings会立即突出显示$1$2在进行第二次正则表达式匹配时没有值。

由于require,当您使用strict时,变量声明中的内容有点粘稠。 A my变量是一个范围有限的严格局部变量。这就是为什么99%的时间使用它。

A my变量只存在于其声明的范围内。例如,如果你声明了一个循环内的变量,它不会在循环外存在:

if ($a > $b) { 
    my $highest = $a; 
} 
else { 
    my $highest = $b; 
} 
print "The highest value is $highest\n"; 

因为$highest是if语句里面定义这是行不通的。你必须申报$highest的声明外,它的工作:

my $highest; 
if ($a > $b) { 
    $highest = $a; 
} 
else { 
    $highest = $b; 
} 
print "The highest value is $highest\n"; 

our声明的变量是全局可用整个。你可以在任何地方定义它 - 在一个循环内部,在一个if语句中,在任何地方 - 它将在稍后提供。

包只是一个名称空间。除非您另行声明,否则您始终处于main包中。防止模块变量影响代码中的变量很有用。这样,您包含的模块可以使用变量$foo,并且您可以使用变量$foo而不会相互干扰。

我不得不这样做的原因是因为你的require。 A my变量仅在其范围内可用。也就是说,for循环,if语句或整个文件。注意上一个:整个文件。这意味着如果我做my %h1,它不会存在于文件之外。因此,我必须声明一个our

此外,当您使用strict时,它是相当严格的。它在发现一个尚未声明的变量时会产生编译时错误。因此,我不得不在主程序中声明%h1,所以编译器知道它。

我也使用say声明,我从我的use feature qw(say);得到。这就像print,除了它总是打印一个NL字符。它看起来并不多,但在许多情况下它可能不那么杂乱。

现在强烈建议您使用声明的标量来打开文件而不是文件句柄。文件句柄是全局的,可能会导致问题。另外,在子程序中很难使用文件句柄。另外,建议使用三部分公开声明。当文件名以>|开头时,这可以防止出现问题。

这里的程序改写了一些更现代的Perl天赋。我保留了标准算法,但添加了新的编译指示,在require之前声明%h1,并使用更标准的open。否则,这几乎是你所拥有的。

#! /usr/bin/env perl 
# 

use strict; 
use warnings; 
use feature qw(say); 

our %h1; 
require "hash.pl"; 


open (my $input_fh, "<", "input.txt") 
    or die "can't open file: $! \n"; 

foreach my $amp (<$input_fh>) { 
    chomp $amp; 
    if ($amp =~ /(\d+)\s+(\d+)\s+(\d+)/) { 
     # Got to save the $1, $2, and $3 for later 
     my $first = $1; 
     my $second = $2; 
     my $third = $3; 
     foreach my $key (keys %h1) { 
      foreach my $tmp1 (@{$h1{$key}}) { 
       if ($tmp1 =~ /($first\s+$second|$second\s+$first)/) { 
        say qq("$key": "$third"); 
       } 
      } 
     } 
    } 
} 
close $input_fh; 
+0

'&!'不是错误信息,'$!'是。 – TLP

+0

或只是'if(my($ first,$ second,$ third)= $ amp =〜/(\ d +)\ t(\ d +)\ t(\ d +)/)' – ysth

+1

错误地匹配部分数字:\/\ A(?:$ first \ s + $ second | $ second \ s + $ first)\ b /' – ysth

相关问题