在perl中将表单布局转换为表(csv)布局

rin*_*rer 0 format perl associative-array

我有一个输入文件

inputfile.txt

        name: George
         age: 5
      nature: curious
       likes: banana
Run Code Online (Sandbox Code Playgroud)

这就是我所说的表单布局.我正在尝试将其转换为表格布局,CSV.例如:

name,age,nature,likes
George,5,curious,banana
Run Code Online (Sandbox Code Playgroud)

所以,我读取文件,拆分为":和\n"并将值放入哈希值.然后将该哈希值推送到数组中,以便稍后将其取出.这是我到目前为止所做的.

#!/usr/bin/perl
use strict;

 open (MYFILE, 'inputfile.txt');
 my @records;
 while (<MYFILE>) {
        chomp;
        my %values = split(/[:\n]/,$_);
        push @records,%values;
 }
 close (MYFILE);
Run Code Online (Sandbox Code Playgroud)

通过这个,我想@records={[name=George],[age=5],[nature=curious],[likes=banana]}会发生.

现在,我如何从阵列中获取每个哈希@records?当我尝试类似的东西:

 foreach my $record(@records){
     my %record = $record;
     for my $key(keys %record){
        print "key : $key\n";
     }
 }
Run Code Online (Sandbox Code Playgroud)

它一个接一个地输出所有令牌,不像预期的那样(只是键).

rai*_*7ow 5

我会以稍微不同的方式做到这一点......

my (@values, @properties);
while (<DATA>) {
  if (/(\S*)\s*:\s*(\S*)/) {
    push @values, $1;
    push @properties, $2;
  }
}
print join ',', @values;
print "\n";
print join ',', @properties;
print "\n";
__DATA__
        name: George
         age: 5
      nature: curious
       likes: banana
Run Code Online (Sandbox Code Playgroud)

......有两个原因.

首先,Perl中的哈希是无序的,并且没有简单的方法将这些属性排序回原始状态.在这些情况下,使用阵列是优选的.

其次,使用正则表达式匹配而不是split允许更容易处理坏数据(在此代码中,模式非常简单,但在那里获得验证逻辑非常容易).此外,立即捕获所有数据块; 你不需要chomp或另外转换它们.


说到你的原始代码:这一行......

push @records, %values;
Run Code Online (Sandbox Code Playgroud)

......不得不改写成......

push @records, \%values;
Run Code Online (Sandbox Code Playgroud)

......表示任何可用的东西.请记住,数组在Perl中是扁平化的,当您尝试将哈希值推入数组时,它只会被转换为一个列表(然后此列表将附加到该数组).

但是,当你必须输出这样的哈希数组时,你必须通过其元素的键,然后浏览其元素的值:如果你只是单独存储它们,就没有必要,就像在我的代码中一样.