我有一个包含以下键和值的数组:
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
有关如何解决此问题以便正常工作的想法吗?
提前致谢。
答案 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
消费者是否有必要这样做。