我正在尝试使用以下代码打印字符串white
和acer
,但它不起作用:
@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处?
答案 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}}