【问题标题】:Push File contents into the array using perl使用 perl 将文件内容推送到数组中
【发布时间】:2020-11-01 23:36:46
【问题描述】:

假设这是我正在阅读的文件

hey how are you
I am fine thank you

这里我想使用一个while循环将文件的内容存储到一个数组中,这样我以后可以轻松地使用该数组而无需再次打开关闭文件。

代码

use warnings;
use strict;

my @point1;
my @point ;

my $log1= "log1.log";

open(IN1, "<$log1" ) or die "Could not open file $log1: $!";
while (my $line = <IN1>) {
    @point = split " ",$line;
    push(@point1,@point);
    push(@point1,"\n");
 }
 
 print "$point1[0] 2nd\n";
 close IN1;
   

输出

hey 2nd

如果我在 while 循环之外打印,我想要如下所示的输出。

我想要的输出:

hey 2nd
I 2nd

我应该在此处进行哪些更改?

【问题讨论】:

    标签: perl


    【解决方案1】:

    您将文件中的所有单词都推送到同一个列表中,这将难以区分它们。

    push(@point1,@point);  
    

    这和做的一样

    @point1 = qw(hey how are you I am fine thank you);
    

    我怀疑你想要的是一个二维数组,这样你就可以提供行号和字号并打印该字,如下所示:

    print $point1[0][0];    # prints "hey"
    

    要做到这一点,你会这样做:

    push @point1, \@point;   # the backslash makes us get the reference to the array
    

    但是您还必须确保所有行不指向 same 数组,就像在循环外声明 my @point 时那样。

    my @point;                          # outside the loop
    while (my $line = <IN1>) {
        @point = split " ",$line;
        push(@point1, \@point);         # wrong
    }
    

    你必须在循环中声明它

    while (my $line = <IN1>) {
        my @point = split " ",$line;    # inside the loop 
        push(@point1, \@point);         # correct
    }
    

    因为这样每次循环迭代都会引用一个新数组,每个新行一个。但是你不需要使用临时变量,你可以直接推送值

    while (my $line = <IN1>) {
        push @point1, [ split " ",$line; ];
    }
    

    方括号创建对匿名数组的引用,其中包含其中的值。之后你可以像这样解决你的任务:

    for my $aref (@point1) {
        print "$aref->[0] 2nd\n";
    }
    

    或者

    for my $line_no (0 .. $#point1) {
        print "$point1[$line_no][0] 2nd\n";
    }
    

    【讨论】:

      【解决方案2】:
      use strict;
      use warnings;
      use feature qw( say );
      
      my $log1 = "log1.log";
      
      open(my $fh, "<", $log1)                        # Don't use a global. Use 3-arg open.
         or die("Can't open file \"$log1\": $!\n");   # No need for the line number.
      
      my @first_words;
      while (my $line = <$fh>) {
          # chomp($line);                 # Not needed with C<< split " " >>, so that was ok.
          my @words = split " ", $line;   # Declare variable to the scope where they are needed.
          push @first_words, $words[0];   # You want the first word of each line.
       }
       
      for my $first_word (@first_words) {   # Need a loop to print stuff repeatedly.
         say "$first_word 2nd";
      }
      

      use strict;
      use warnings;
      use feature qw( say );
      
      my @first_words;
      while (my $line = <>) {
          my @words = split " ", $line;
          push @first_words, $words[0];
       }
       
      for my $first_word (@first_words) {
         say "$first_word 2nd";
      }
      

      第二个更灵活。只需将所需的文件名作为参数传递。它还可以通过 STDIN 处理输入。

      【讨论】:

        【解决方案3】:

        目前还不清楚您要查找的数据结构。这里有几种可能性。

        您希望文件的每一行都包含在数组中的一个元素中。

        my @array = <$fh>;
        

        您希望文件的每一行都包含在数组中的一个元素中,但您还希望将输入拆分为单个单词(因此您最终会得到一个数组数组)。

        my @array = map { [ split ] } <$fh>;
        

        您需要数组中元素中每一行的第一个单词。

        my @array = map { (split)[0] } <$fh>;
        

        我之前提到过,您应该改用三参数版本的open() 和词法文件句柄。因此,假设我上面的所有代码示例都以:

        open my $fh, '<', $log1 or die "Cannot open '$log1': $!\n";
        

        回顾你最近的几个问题,我不禁认为这是X/Y question。您要求我们帮助解决构成您代码一部分的小问题,但实际上,如果我们对全局有更多了解,我们可以提供更好的帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-21
          • 2010-10-09
          相关资源
          最近更新 更多