将perl数组排序为固定顺序

时间:2017-03-17 11:13:07

标签: arrays perl sorting hash

我有一个包含以下键和值的数组:

 atest, 2
 ctest, 3
 btest, 8
 ftest, 1
 gtest, 6

我将它们从一个文件解析成一个数组。现在我想每次都按照这个顺序返回它们。 但是我无法让它发挥作用。

来源:

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


 my @data;
 my %tags;
 my $cur_tag;
 my ($tag,$line);
 open (FILE, '<', $ARGV[0]) or die "Could not open file: $!";
 while (<FILE>) {
chomp;
if (/^(MyValStart)/)
    { push @data, {} }
elsif (  ($tag,$line) = (/^\s*(atest)\s+(.+)$/)) {
    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(ctest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    #print ($line,"\n");
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(itest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(btest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(ytest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(ftest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(gtest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif (  ($tag,$line) = (/^\s*(utest)\S\s+(.+)$/)) {

    $data[-1]{$tag} .= " NEWLINE " if exists $data[-1]{$tag};
    $data[-1]{$tag} .= $line;
    $tags{$tag}++;
    $cur_tag = $tag;
}
elsif ($cur_tag) {
    $data[-1]{$cur_tag} .= " NEWLINE ".$_;
}
 }

 use Text::CSV;
 my $csv = Text::CSV->new({binary=>1,auto_diag=>2,eol=>"\n",
sep_char=>";",always_quote=>1,blank_is_undef=>1});
%tags=qw/atest ctest btest ftest gtest/;

$csv->print(select, [%tags]);
for my $row (@data) {
my @vals = map { $row->{$_} } %tags;
$csv->print(select, \@vals);
 }

从源可见时,还有一些我解析到数组中的东西,后来没有用于打印输出。 我无法解决这两个问题。

我想要的输出仅用于atest,ctest,btest,ftest和gtest的值,如

"2"; "3"; "8"; "1"; "6"
"1"; "5"; "2"; "0"; "5"

返回的数字也可以是多行的单词或句子,但这已经有效了。

输入文件如下:

 MyValStart
 ---------------

     atest:    2
     ctest:    3
     itest:    3
     btest:    8
     ytest:    3
     ftest:    1
     gtest:    6
     utest:    348385fhjdhgofdgkdfjgd



 MyValStart
 ---------------

     atest:    1
     ctest:    5
     itest:    3
     btest:    2
     ytest:    jfdgdf ifdgijfdjgoksfk iosjfdjdisfpgj
     ftest:    0
     gtest:    5
     utest:    jfsdhgjfd fighfidhg ifhdghfid ifdhjgifdh

有关如何解决此问题以便正常工作的想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

如果我正确地阅读你的代码,那你就是这么做的。我建议您应该做的是将输入读取并解析为合理的数据结构,然后以所需的格式输出。

由于您拥有键值对的“数据”块,并且您需要提取命名值 - 哈希数组将成为作业的工具。将每个'chunk'读入哈希,然后将其插入到数组中。

然后获取该哈希数组,并使用hash slices提取所需的值 - 按键排序。

这样的事情:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

#read input data:
my @rows; 

#set record separator to 3 line feeds.     
local $/ = "\n\n\n";
while ( <> ) {
   next unless m/test/;
   #map key-values out of this 'chunk'. 
   my %row = m/(\w+):\s*(\S.*)/g; 
   push @rows, \%row; 
}

#print whole data structure for debugging:
print Dumper \@rows;

#define columns and ordering for output:
my @output_cols = qw ( atest ctest btest ftest gtest );

#iterate rows
foreach my $row ( @rows ) {
    #print fields selected from output_cols. 
   #use a 'hash slice' - look it up in perl docs. 
   print join ";", @{$row}{@output_cols},"\n"
}

这给出了

的输出
2;3;8;1;6;
1;5;2;0;5;

我们使用记录分隔符$/将我们的输入分解为不是仅仅换行的“默认”的块。

这与你提出的不完全相同,因为没有引号。如果你想要,你可以map

print join ";", (map { '"'.$_.'"' } @{$row}{@output_cols}),"\n"

但我不确定大多数csv消费者是否有必要这样做。