2011-08-01 27 views
1

我一直在试图编写一个程序来读取文本格式的数字列到Perl变量中。从文件读取数字到变量(Perl)

基本上,我有一个说明和数字文件:

ref 5.25676  0.526231  6.325135 
ref 1.76234  12.62341  9.1612345 

我希望把数字与不同的名称,如变量

ref_1_x=5.25676 
ref_1_y=0.526231 

这里是我到目前为止有:

print "Loading file ..."; 
open (FILE, "somefile.txt"); 
@text=<FILE>; 
close FILE; 
print "Done!\n"; 
my $count=0; 
foreach $line (@text){ 
    @coord[$count]=split(/ +/, $line); 
} 

我想比较写入的文件到对方的位置,这样就需要另一个循环在这之后。

+0

所以你想比较文件中不同行的数字? – Zaid

回答

4

对不起,你不是很清楚你想要做什么以及“ref”是指什么。如果我误解了你的问题,请指出并澄清。所有的


首先,我会强烈建议不要使用可变构建数据(例如,使用$ref_1_x存储X具有标签“REF”坐标的第一行)。

如果你想存储x,y和z坐标,你可以像3个元素一样存储数据,就像你做的一样 - 唯一的区别是你想存储一个数组引用(你可以“T存储数组作为值在在Perl另一个阵列):

my ($first_column, @data) = split(/ +/, $line); # Remove first "ref" column 
@coordinates[$count++] = \@data; # Store the reference to coordinate array 

然后,访问的x坐标行2,这样做:

$coordinates[1]->[0]; # index 1 for row 2; then sub-index 0 for x coordinate. 

如果你坚持存储在指定的数据结构中的3个坐标,因为sub-index 0 for x coordinate看起来的可读性 - 这是在一般一个有效的关注,但没有真正与3列的问题 - 使用散列而不是数组:

my ($first_column, @data) = split(/ +/, $line); # Remove first "ref" column 
@coordinates[$count++] = { x => $data[0], y => $data[1], z => $data[2] }; 
# curly braces - {} - to store hash reference again 

然后,访问的x坐标第2行,你这样做:

$coordinates[1]->{x}; # index 1 for row 2 

现在,如果你也想存储具有第一列值在一个单独的“裁判”,“裁判”的行 - 标记数据结构,你可以通过包装原来的@coordinates a来实现用“ref”键作为散列值。

my ($label, @data) = split(/ +/, $line); # Save first "ref" label 
$coordinates{$label} ||= []; # Assign an empty array ref 
          #if we did not create the array for a given label yet. 
push @{ $coordinates{$label} }, { x => $data[0], y => $data[1], z => $data[2] }; 
# Since we don't want to bother counting per individual label, 
# Simply push the coordinate hash at the end of appropriate array. 
# Since coordinate array is stored as an array reference, 
# we must dereference for push() to work using @{ MY_ARRAY_REF } syntax 

然后,访问的x坐标为标签的“参考”第2行,你这样做:

$label = "ref"; 
$coordinates{$label}->[1]->{x}; # index 1 for row 2 for $label 

而且,你原来的示例代码有几个你可能要过时的成语写入更好的风格(使用3参数形式open(),检查IO操作上的错误,如open();使用词法文件句柄;将整个文件存储在大数组中,而不是逐行读取)。

这里有一个稍作修改的版本:

use strict; 
my %coordinates; 
print "Loading file ..."; 
open (my $file, "<", "somefile.txt") || die "Can't read file somefile.txt: $!"; 
while (<$file>) { 
    chomp; 
    my ($label, @data) = split(/ +/); # Splitting $_ where while puts next line 
    $coordinates{$label} ||= []; # Assign empty array ref if not yet assigned 
    push @{ $coordinates{$label} } 
     , { x => $data[0], y => $data[1], z => $data[2] }; 
} 
close($file); 
print "Done!\n"; 

目前尚不清楚你要比较什么什么,所以没有进一步澄清对不能提供建议。

+0

+1同上推荐 – Axeman

0

问题是你可能需要一个双数组(或散列或...)。取而代之的是:

@coord[$count]=split(/ +/, $line); 

用途:

@coord[$count++]=[split(/ +/, $line)]; 

这使分裂的整个结果成子阵列。因此,

print $coord[0][1]; 

应输出“5.25676”。

+0

这有一个“bug”(特征?),因为它将第一个“ref”列与坐标 – DVK

+0

一起存储在数组中它是一个特征;-)使用附加拼接如果你真的不想要这样做的话。拼接(分割(),0,1); –