将哈希值从字符串更改为数组

时间:2013-06-04 22:45:51

标签: perl

data.txt中

 Name:xyz
 ID:1
 Value: 1 2 3 4 5 6 7 8 9 ...
 ID:2 
 Value: 9 8 7 6 5 4 3 2 1..
 ID:3
 Value: 90 89 88....
 Name:abc
 ID:11
 value:...

Intial file.txt

## Header 
..
data
data
data
..

最终预期的file.txt

## Header xyz_1,xyz_2,xyz_3,abc_11,...
..
data 1 9 90
data 2 8 89
data 3 7 88
data 4 6 
..

当前输出file.txt

## Header xyz_1,xyz_2,xyz_3,abc_11,...
...
data, 1 2 3 4 5 6 7 8 9 ..,9 8 7 6 5 4 3 2 1 ..,90 89 88
data
data
...

代码

#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;

use Tie::File;

my @name_id;
my %test;

#local $/ = '';

open my $fh, '<', 'data.txt' or die "failed: $!";
my %var;
while (<$fh>) {
  chomp;
  if (m/^([A-Z:]+):\s*(.*)/) {
    $var{$1} = $2;
    if (exists($var{Name}) && exists($var{ID}) && exists($var{value}) && $1 eq 'value') {
      my $var_name = "$var{Name}_$var{ID}";
      push @name_id, $var_name;
      $test{$var_name} = $var{value};
    }
  }
}

#   print join "\n\t", @test{@name_id};
my $match = "## Header";
tie my @lines, 'Tie::File', 'file.txt' or die "failed : $!";
for my $line (@lines) {
  if ($line =~ /^($match.*)/) {
    $line = $1 . "," . join ',', @name_id;
  }
}
untie @lines;

my $match = "data";
tie my @lines, 'Tie::File', 'file.txt' or die "failed : $!";
my $i = 0;
for my $line (@lines) {
  if ($line =~ /^($match.*)/) {
    $line = $1 . "," . join(',', map { $test{$_}->[$i] } @name_id);
    $i++;
  }
}
untie @lines;

此行$line = $1 . "," . join (',', map { $test{$_}->[$i]} @name_id);出现问题会引发错误

  

不能使用字符串(“1 2 3 4 5 6 7 8 9 ..”...)作为ARRAY ref,而在test.pl第46行,第80行使用“strict refs”时,测试时。第46行

我认为我的哈希值(%test)是一个字符串,我无法将其拆分为数组。请告诉我如何将其转换为数组。我试过$test{$var_name} = [qw($var{value})];它没有用。

3 个答案:

答案 0 :(得分:3)

您可能对您的代码重构感兴趣,似乎可以按照您的意愿进行。

#!/usr/local/bin/perl
use strict;
use warnings;

use Tie::File;

open my $fh, '<', 'data.txt' or die "failed: $!";

my @name_id;
my %test;
my %var;

while (<$fh>) {
  chomp;
  if (my ($key, $val) = /^(\w+):\s*(.*)/) {
    $var{$key} = $val;
    if ($key eq 'value') {
      my $var_name = "$var{Name}_$var{ID}";
      push @name_id, $var_name;
      $test{$var_name} = [ split ' ', $var{value} ];
    }
  }
}

tie my @lines, 'Tie::File', 'file.txt' or die "failed : $!";
my $count = 0;
for my $line (@lines) {
  if ($line =~ /^## Header/) {
    $line .= ' ' . join ',', @name_id;
  }
  elsif ($line =~ /^data/) {
    $line .= ' ' . join ' ', map { $test{$_}[$count] // '' } @name_id;
    $count++;
  }
}
untie @lines;

输出file.txt

## Header xyz_1,xyz_2 ,xyz_3
data 1 9 90
data 2 8 89
data 3 7 88
data 4 6 

答案 1 :(得分:1)

这肯定是不对的:

$test{$_}->[$i]

因为$test{$_}只能包含某种字符串。

如果你有一个字符串并且想要拆分成一个arrayref以便上面的工作,那就这样做:

$test{$var_name} = [split /\s+/, $var{value}];

我不知道代码应该完成什么,这意味着它可以运行,但我不知道它是否符合它的意图。奇怪的变量名称(如$test$var_name并没有帮助我理解目的)。

答案 2 :(得分:0)

我不太确定我是否遵循了您的代码,但我认为我会发布如何转置数字(除非您的代码已经执行了此操作:-))。

#!/usr/bin/perl
use strict;
use warnings;

my (%data, $name);
while (<DATA>) {
    if (/^Name:(.+)/) {
        $name = $1  
    }
    elsif (/^Value/) {
        # transpose
        my $r = 0;
        push @{ $data{$name}[$r++] }, $_ for /\d+/g;
    }   
}

use Data::Dumper; print Dumper \%data;

__DATA__
Name:xyz
ID:1
Value: 1 2 3 4 5 6 7 8 9
ID:2 
Value: 9 8 7 6 5 4 3 2 1
ID:3
Value: 90 89 88 87 86 85 84 83 82
Name:abc
ID:11

转储的结果是:

$VAR1 = {
          'xyz' => [
                     [
                       '1',
                       '9',
                       '90'
                     ],
                     [
                       '2',
                       '8',
                       '89'
                     ],
                     [
                       '3',
                       '7',
                       '88'
                     ],
                     [
                       '4',
                       '6',
                       '87'
                     ],
                     [
                       '5',
                       '5',
                       '86'
                     ],
                     [
                       '6',
                       '4',
                       '85'
                     ],
                     [
                       '7',
                       '3',
                       '84'
                     ],
                     [
                       '8',
                       '2',
                       '83'
                     ],
                     [
                       '9',
                       '1',
                       '82'
                     ]
                   ]
        };