问题很简单:你在你的程序中使用$1
, $2
, $3
,但是当你使用它们时,你已经失去了它们的价值。这些是全局符号,只要您使用正则表达式运算符,它们就会被替换。在您的第一次正则表达式匹配后,只需将它们保存在另一个变量中:
$first = $1;
$second = $2;
$third = $3;
您还应该小心使用正则表达式。您的正则表达式有效,但它们非常非常狭窄。当您第一次在文件中有标签时,我错过了它。我喜欢使用\s+
任何类型的空白。这将涵盖多个制表符或空格或不同的组合。
我还强烈建议您学习一些更现代的 Perl。如果您在程序中使用了这两行代码,您会立即发现问题:
use strict;
use warnings;
这strict
将确保您已通过my
或定义了变量our
。这样可以确保您不会说$Foo
一个又$foo
一个,并且想知道您存储的价值发生了什么变化$foo
。
当您进行第二次正则表达式匹配时warnings
,会立即突出显示$1
并且$2
没有值。
因为,require
当你使用strict
. my
变量是具有有限范围的严格局部变量。这就是为什么 99% 的时间都在使用它。
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
。my
变量仅在其范围内可用。也就是说,for 循环、if 语句或整个文件。请注意最后一个:整个文件. 这意味着如果我这样做my %h1
,它就不会存在于文件之外。因此,我必须用our
.
此外,当您使用 时strict
,它非常严格。当它看到一个尚未声明的变量时,它会生成一个编译时错误。因此,我必须%h1
在主程序中声明,以便编译器知道它。
我也使用say
从我的use feature qw(say);
. 就像print
它总是打印一个 NL 字符。它看起来并不多,但在许多情况下它可以不那么混乱。
现在强烈建议您使用声明的标量来打开文件,而不仅仅是文件句柄。文件句柄是全局的,可能会导致问题。另外,在子程序中很难使用文件句柄。另外,建议使用三部分的 open 语句。这可以防止文件名以>
或开头时出现问题|
。
这是用更现代的 Perl 风格重写的程序。我保留了您的标准算法,但添加了新的编译指示,在 ing%h1
之前声明require
,并使用了更标准的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;