我有一个名为' dataexample'的文本文件。像这样的多行:
a|30|40
b|50|70
然后我用这段代码分割分隔符:
open(FILE, 'dataexample') or die "File not exist";
while(<FILE>){
my @record = split(/\|/, $_);
print "$record[0]";
}
close FILE;
当我print "$record[0]"
时,这就是我得到的:
ab
我的期望:
a 30 40
所以当我print "$record[0][0]"
时,我希望输出为:a
哪里弄错了?
答案 0 :(得分:4)
您的循环while ( <FILE> ) { ... }
一次从文件句柄读取一行并将其放入$_
my @record = split(/\|/, $_)
在管道字符|
上拆分该行,因此第一行是"a|30|40\n"
,@record
现在将是'a', '30', "40\n"
。从文件中读取的换行符仍然存在,如果您不想在那里删除,则应使用chomp
将其删除
所以现在$record[0]
是a
,您打印,然后继续阅读文件中的下一行,这次将@record
设置为'b', '50', "70\n"
。现在$record[0]
为b
,您也会打印,在控制台上显示ab
您现在已到达文件末尾,因此while
循环终止
这听起来像是你期待一个二维数组。你可以通过在每次读取记录时将每个数组推到主数组上来实现,比如
use strict;
use warnings 'all';
open my $fh, '<', 'dataexample' or die qq{Unable to open "dataexample" for input: $!};
my @data;
while ( <$fh> ) {
chomp;
my @record = split /\|/;
push @data, \@record;
}
print "@{$data[0]}\n";
print "$data[0][0]\n";
a 30 40
a
或者,更简洁,像这样,产生完全相同的结果,但可能会有点先进
use strict;
use warnings 'all';
open my $fh, '<', 'dataexample' or die qq{Unable to open "dataexample" for input: $!};
my @data = map { chomp; [ split /\|/ ] } <$fh>;
print "@{$data[0]}\n";
print "$data[0][0]\n";
了解自己代码的一些要点
您必须始终 use strict
和use warnings 'all'
位于您编写的每个Perl程序的顶部。这是一个可以发现许多你可能没有注意到的简单错误的措施
您应该将词汇文件句柄与三参数表单或open
一起使用。由于文件不存在的其他许多原因,open
可能会失败,因此您应该在$!
字符串中加入内置的die
变量,以说为什么失败了
请勿忘记chomp
从文件中读取的每条记录,除非您想保留后续的新行或对您不重要
如果您习惯使用默认变量 $_
,您将能够编写更简洁的代码。例如,split
的第二个参数默认为$_
,因此split(/\|/, $_)
可能只写为split /\|/
您可以使用Data::Dumper
显示变量的内容,这将有助于您调试代码。 Data::Dump
是优越的,但它不是核心模块,因此您可能必须先安装它才能在代码中使用它
答案 1 :(得分:3)
你必须使用
print "$record[1]";
print "$record[2]";
因为它们存储在连续的索引值中。
或
如果你想打印整件事,你可以做
print "@record\n";
答案 2 :(得分:2)
每次循环时都会在数组的第一个索引处打印值,而不使用新行。因此,您从每一行获得第一个值,在同一行上彼此相邻,因此ab
。
使用新行在引号下打印整个数组。你的程序改变了一点
use strict;
use warnings;
my $file = 'dataexample';
open my $fh, '<', $file or die "Error opening $file: $!";
while (<$fh>) {
chomp;
my @record = split(/\|/, $_);
print "@record\n";
}
close $fh;
使用引号打印元素时,在它们之间添加空格,以便
a 30 40 b 50 70
如果您在没有引号的情况下进行打印,则会打印元素而不会留出额外的空格 此
print @record, "\n";
整个循环打印
a3040 b5070
如果你没有新的行"\n"
,那么它全部打印在一行上,所以这个
print @record;
完全打印
a3040b5070
对于$record[0][0]
,这对您拥有的数组无效。这将从二维数组打印。举个例子,
my @data = ( [1.1, 2.2], [10, 20] );
此数组@data
在其第一个索引处具有对数组的引用 - 更确切地说,是匿名数组 [1.1, 2.2]
。它的第二个元素是匿名数组[10, 20]
。所以$data[0][0]
是:@data
的第一个元素(所以内部的两个匿名数组中的第一个),然后是该数组的第一个元素,即1.1
。同样地,$data[1][1]
是20
。
感谢Sobrique发表评论。
但是你的程序中没有这个。将数据拆分为数组时
while(<FILE>){
my @record = split(/\|/, $_);
# ...
}
每次循环都会创建一个名为@record
的新数组。所以@record
是一个普通数组,而不是二维数组。为此,语法$record[0][0]
并没有多大意义。
答案 3 :(得分:1)
我认为您正在尝试创建一个二维数组,其中每个元素都包含输入每行的所有管道分隔项:
my @record;
while(<DATA>){
chomp;
my @split = split(/\|/);
push @record, [@split];
}
print "@{$record[0]}\n";
a 30 40
答案 4 :(得分:0)
record[0]
包含第1列的内容 - &#39; a&#39;在循环的第一次迭代中,&#39; b&#39;在第二个。 record[1]
有第2列,依此类推。您将打印语句print "record[0]"
放入循环中,以便获得&#39; a&#39;在第一次迭代中打印并且&#39; b&#39;在第二个。
要获得您想要的内容,您需要用;
替换print语句print join " ", @record, "\n";