【问题标题】:Why is Perl script asking for 'global declaration' when I declare something in for loop?当我在 for 循环中声明某些内容时,为什么 Perl 脚本会要求“全局声明”?
【发布时间】:2009-08-05 02:57:47
【问题描述】:

我正在从 infile 读取 $digit,并希望将其打印到 outfile。但是 Perl 脚本给出了一个错误,提示“全局符号“$digit”需要明确的包名”。但是,如果我确实将其声明为全局 $digit='',则此值将打印到 outfile,而不是从 infile 中提取/读取的值。关于应该做什么有什么建议吗?

这就是我的做法:

    my $digit=''; 
    open (DATA, "</usr/infile") || die "cant open infile\n"; #file from digit has to read

    while (<DATA>){
        ($digit)= $_=~ /\s9\s(\d+)/; #regex to capture digit '234' from ' 9 234'
        if ($digit ne ""){
        print "digit is $digit\n"; # this prints fine
        }
    }

    open (FILE, ">/usr/outfile") || die "cant open outfile\n"; #file to which digit has to be finally written
    print FILE "9   $digit"; #$digit takes in the value declared globally i.e. ''

    close(DATA);
    close (FILE);

【问题讨论】:

  • 与您的问题无关:请包含 $!在你的死亡信息中。例如:死“/usr/infile:$!”
  • DATA 文件句柄是特殊的。不要破坏了解 Perl 的人的合理假设。此外,无论如何,您都应该使用词法文件句柄。所以,使用open my $data ...
  • @Sinan:这对我的问题有帮助吗?
  • 请向我们展示说明问题的输入和输出。在您最近的编辑中,只有一个变量$digit,其词法范围涵盖整个脚本(或多或少)和while 循环。那么,发生了什么是输入文件/usr/infile 的最后一行与您的正则表达式不匹配,因此将$digit 设置为undef,当您打印它时,它看起来很像空白字符串。 :)
  • @shubster 我不知道这是否对您当前的问题有所帮助,但它肯定会减少您必须阅读的内容才能为您提供帮助。帮助别人帮助你。

标签: perl error-handling global-variables


【解决方案1】:

您的 $digit 被限定在 while 循环内,然后您尝试使用以下行在其外部访问它:

print FILE "9   $digit";

您必须在 while 循环之外声明它才能被该行看到。

或者更好的是,在循环之前打开您的输出文件并将数字写入循环内的输出文件,并将您的 $digit 变量保持在循环范围内。

如果您只想要与您的正则表达式匹配的最后一个实例,那么:

#!/usr/bin/perl
use strict;

open (DATA, "infile.txt")  || die("cant open infile\n");   

my $digit = "";
while (<DATA>) {
    chomp;
    if (/\s9\s(\d+)/) #regex to capture digit '234' from ' 9 234' 
    {
       print "Found digit is $1\n"; # 
       $digit = $1;
    }
}
close(DATA);

if ($digit ne "") {
open (FILE, ">outfile.txt") || die("cant open outfile\n"); 
print FILE "9   $digit\n";
close(FILE);
}
else
{
    print "No digit found!\n";
}
exit;

如果您想获取 infile 中与您的正则表达式匹配的所有实例,以下应该可以解决问题。

#!/usr/bin/perl
use strict;

open (DATA, "</usr/infile")  || die("cant open infile\n");   
open (FILE, ">/usr/outfile") || die("cant open outfile\n"); 

while (<DATA>) {
    chomp;
    if (/\s9\s(\d+)/) #regex to capture digit '234' from ' 9 234' 
    {
       print "Found digit is $1\n"; # 
       print FILE "9   $1\n";
    }
}


close(DATA);
close (FILE);
exit;

【讨论】:

  • @RC:正如我所说,如果我在外面声明它,那么它会采用该值(即声明它的值),而不是使用正则表达式捕获的值。所以你的建议是行不通的。
  • 在外面声明它时没有被捕获的原因是 b/c my $digit;在您的 while 循环中是由正则表达式分配的,而不是全局的。由于 while 内的 $digit 在 while 右大括号处超出范围,因此您最终会使用全局 $digit 值而不是您在循环中设置的值写入 outfile。
  • @RC:那么有没有办法将 $digit 写入 outfile 并使用正则表达式捕获它的值?
【解决方案2】:
while (<DATA>){
    my ($digit)= $_=~ /\s9\s(\d+)/; #regex to capture digit '234' from ' 9 234'
    if ($digit ne ""){
    print "digit is $digit\n"; # this prints fine
    }
}

词法变量(使用 my 创建的)存在于它们声明的范围内,因此每次循环都会创建和销毁 $digit。

【讨论】:

  • @Chas.Owens:那么有没有其他方法可以将 $digit 写入另一个文件?
【解决方案3】:

不要在 while() 循环中声明 $digitmy;就在外面声明:

my $digit;
while( <DATA> ) {
    # stuff that sets $digit... 
}

open( FILE , '>out' );
print FILE $digit;

【讨论】:

  • 此外,不要在循环内使用my ($digit),因为它声明了另一个变量,称为$digit
  • 对,一旦你用my 声明了$digit 一次,不要再声明它,直接使用它。 @RC,如果你不止一次使用my,你所说的就会发生——while 中的变量被遮蔽了。
  • @genehack:正如我所提到的,在这样做时,写入 'out' 的 '$digit' 会采用声明它的值,即 '' 而不是使用正则表达式捕获的值.
  • @shubster 发布了您说当时不起作用的修改后的代码——此时有 3 个人(我、Greg 和 RC)都在告诉您完全相同的事情,所以如果您'会声称它不起作用,显示你在做什么不起作用 - 因为从你到目前为止所说的,我们三个人都说的是,嗯,对。
  • 太棒了,现在从while() 循环的第一行删除'my',这样它就变成了:while () { ($digit) = $_ =~ /blahregexp /;看看这是否效果更好。 (不过,Chas 是对的,因为 $digit 可能仍会被其他行踩到;RC 是对的,您可能应该只从循环内部输出 $digit。)
【解决方案4】:

您已使用my$digits 声明为while 循环范围的本地。 print 语句中的 $digit 超出范围,这就是导致该消息的原因。

要更正此问题,请在 while 循环之前声明 my $digit 或使用 our 而不是 my 声明它以使其全局化。

我会做以下事情:

use strict;
use warnings;

my $digit = "None";  # None if there are no digits found

open (DATA, "</usr/infile") || die "cant open infile\n"; #file from digit has to read
while (<DATA>){    
    ($digit) = $_=~ /\s9\s(\d+)/; #regex to capture digit " 9 234"    
    if ($digit ne ""){    
        print "digit is $digit\n"; # this prints fine    
    }
}
open (FILE, ">/usr/outfile") || die "cant open outfile\n"; #file to which digit has to be finally written
print FILE "9   $digit";
close(DATA);
close(FILE);

如果您没有获得数字,您将获得“无”$digit

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2015-03-25
    • 2012-04-29
    • 2011-09-02
    • 2015-10-24
    相关资源
    最近更新 更多