2

编程新手。任务是从字符串中提取特定数据,我选择编写代码如下 -

while ($line =<IN>) {
    chomp $line;
    @tmp=(split /\t/, $line); 
    next if ($tmp[0] !~ /ch/); 
    @tgt1=@tmp[8..11];
    @tgt2=@tmp[12..14];
    @tgt3=@tmp[15..17];
    @tgt4=@tmp[18..21];
    foreach (1..4) {
            print @tgt($_), "\n";
            }

我以为@tgt($_)会被解释为,@tgt1, @tgt2, @tgt3, @tgt4但我仍然收到@tgt作为全局符号的错误消息(@tgt1、@tgt2、@tgt3、@tgt4` 已被声明)。

Q1。我误解了 foreach 循环吗?

Q2。为什么 perl 看不到@tgt($_)@tgt1、@tgt2 ..etc?

Q2。根据经验,这可能是命名变量的不好方法。命名具有相似特征的变量的首选方法是什么?

4

1 回答 1

7
  • Q2。为什么 perl 不能将 @tgt($_) 视为 @tgt1、@tgt2 ..etc?

  • Q2。根据经验,这可能是命名变量的不好方法。命名具有相似特征的变量的首选方法是什么?

我会一起回答。

@tgt($_)并不意味着你希望它意味着什么

  • 首先,这是一个无效的语法(你不能在数组名之后使用 (),perl interpeter 会产生编译错误)。

  • 您要做的是通过表达式访问变量来访问不同的变量,从而产生其名称(又名符号引用)。这是可以做到的;但通常是一个坏主意和糟糕的 Perl(例如,你可以但你不应该这样做,没有非常好的理由)。

  • 要以您尝试的方式访问元素 $_,请使用@{"tgt$_"}语法。但我再说一遍 -不要那样做,即使你可以。

  • 一个正确的惯用解决方案:使用 arrayrefs 数组,您的 1-4(或更确切地说是 0-3)索引外部数组:

     # Old bad code: @tgt1=@tmp[8..11];
    
     # New correct code:
     $tgt[0]=[ @tmp[8..11] ]; # [] creates an array reference from a list.
     # etc... repeat 4 times - you can even do it in a smart loop later.
    

    它的作用是将数组切片的引用存储到单个@tgt数组的第零个元素中。

    最后,@tgt数组有 4 个元素,每个元素都是对包含其中一个切片的数组的数组引用。


  • Q1。我误解了 foreach 循环吗?

您的 foreach 循环(与其内容相反 - 见上文)是正确的,但有一种风格警告 - 同样,虽然您可以使用默认$_变量,但您几乎不应该使用它,而是始终使用命名变量以提高可读性。

您按如下方式打印上述 arrayrefs 数组(单独询问是否有任何语法不清楚 - 这是一个中级数据结构处理,不适合初学者):

foreach my $index (0..3) { 
    print join(",", @{ $tgt[$index]}) . "\n";
}
于 2013-07-10T18:46:55.847 回答