如何将__DATA__读入数组,以便每个单词都有自己的索引?

时间:2014-03-05 16:38:22

标签: perl

我正在尝试使用以下代码打印字符串whiteacer,但它不起作用:

@a=<DATA>;
print "$a[9] $a[14]";

__DATA__
one two three four five six seven
black yellow white green
apple orange 
hp acer samsung 

如何将__DATA__读入数组,以便white位于索引9而acer位于索引14处?

4 个答案:

答案 0 :(得分:4)

如果您使用Data::Dumper检查“数组”,您将看到它只有四个元素,因此未定义索引“9”和“14”:

use strict;
use warnings;

use Data::Dumper;

my @a = <DATA>;

print Dumper \@a;

# prints 
#[
#          'one two three four five six seven
#',
#          'black yellow white green
#',
#          'apple orange 
#',
#          'hp acer samsung 
#'
#]

__DATA__
one two three four five six seven
black yellow white green
apple orange 
hp acer samsung

答案 1 :(得分:4)

如果您希望每个单词占据阵列的一个元素,则需要处理各个行。

split函数将字符串(默认情况下为空格)拆分为字符串列表:

my @a = map +split, <DATA>;
print $a[9], "\n";  # 'white'
print $a[14], "\n"; # 'acer'

答案 2 :(得分:3)

首先,总是 use strict; use warnings;位于每个脚本的顶部。这些编译指示将帮助您避免脚本中的问题。另外,使用词汇变量,即使用my声明的词汇变量。

如上所述,实现结果的一种方法是遍历所有DATA行,split每行@a。这是一种非常常见的方法(正如您通常对文件所做的那样):

use strict;
use warnings;

my @a;
while (<DATA>) {
    push @a, split;
}

print "$a[9] $a[14]"; # Prints white acer

__DATA__
one two three four five six seven
black yellow white green
apple orange 
hp acer samsung

请注意,split没有任何显式参数。在这种情况下,它相当于split ' ', $_,即默认标量$_中的行在空格上为split

另一种方法是在一个块中“啜饮”所有数据,然后split读取的内容:

use strict;
use warnings;

local $/;
my @a = split ' ', <DATA>;
print "$a[9] $a[14]"; # Prints white acer

__DATA__
one two three four five six seven
black yellow white green
apple orange 
hp acer samsung

local $/;行可让您一次读取所有数据。

希望这有帮助!

答案 3 :(得分:2)

虽然slurping(如my @a = <DATA>my @a = map +split, <DATA>)对于短文件似乎没问题,但最好逐行读取以使程序的内存占用与最大输入行成比例而不是文件的大小。

如果你要啜饮,最好将文件作为单个字符串读取,如Kenosis' answer的第二部分所示。答案的第一部分是你应该使用的。

不带参数的split的替代方法是使用捕获模式仅保留非空格字符序列,如下所示:

my @words;
push @words, /(\S+)/g while <DATA>;

在列表上下文中,/(\S+)/g将返回一行中所有非空格字符序列。如果没有明确的绑定,它会在$_上匹配,DATA会逐行填充#!/usr/bin/env perl use strict; use warnings; my @words; push @words, /(\S+)/g while <DATA>; use Data::Dumper; print Dumper \@words; __DATA__ one two three four five six seven black yellow white green apple orange hp acer samsung

push @words, /(\S+)/g while <DATA>;

输出:

VAR1 = [
          'one',
          'two',
          'three',
          'four',
          'five',
          'six',
          'seven',
          'black',
          'yellow',
          'white',
          'green',
          'apple',
          'orange',
          'hp',
          'acer',
          'samsung'
        ];

现在,而

split

行看起来很整洁,它确实为每一行创建了一个临时列表。如果你有很多字段的行,你可以通过显式循环节省一些内存开销(这是my @words; while (<DATA>) { while (/(\S+)/g) { push @words, $1; } } 无法做到的事情):

push @words, split while <DATA>;

然而,在没有其他替代方案的好处的证据的情况下,我的默认选择是与Kenosis的建议一致:

{{1}}