Imprimir / exportar o arquivo csv para o array

0

Eu tenho os seguintes dados em um csv muito grande:

"sortorder","name","description"
"1","B.1","Boiler room"
"2","1.1","First office"
"3","1.2","Second office"
etc...

Que eu gostaria de terminar assim:

{ name => 'B.1', description => 'Boiler room', sortorder => 1 },
{ name => '1.1', description => 'First office', sortorder => 2 },
{ name => '1.2', description => 'Second office', sortorder => 3 },
etc.

Como posso conseguir isso em algo com perl ou bash?

    
por Martin 11.07.2016 / 18:34

3 respostas

1

Solução geral sed (sem o recurso de campos)

sed '
    1{
        h
        d
    }
    G
    :a
    s/\(^\|,\)\([^=]\+\n\)"\?\([^,]\+\)"\?,\?/  => /
    ta
    s/^/{/
    s/\n/ },/
    ' file.csv

Mas se você quiser que o primeiro campo seja o último - apenas adicione

s/\([^,]*\), \([^\n]*\)/, /

depois de ta

    
por 11.07.2016 / 19:21
1

Um pequeno rubi de uma linha

  ruby -rcsv -ne '
    row = CSV.parse_line($_)
    if $. == 1 then
      keys = row
    else
      h = Hash[keys.zip(row)]
      puts h.to_s + ","
    end
  '

saídas

{"sortorder"=>"1", "name"=>"B.1", "description"=>"Boiler room"},
{"sortorder"=>"2", "name"=>"1.1", "description"=>"First office"},
{"sortorder"=>"3", "name"=>"1.2", "description"=>"Second office"},

ou Perl, que gera a estrutura de dados completa (matriz de hashes)

use strict;
use warnings;
use v5.10;

use Text::CSV;
use autodie;
use Data::Dump      qw/ dump /;

my @rows;
open my $fh, "<", shift @ARGV;
my $csv = Text::CSV->new( {binary => 1} );
my $keys = $csv->getline($fh);
while (my $row = $csv->getline($fh) ) {
    my %h;
    @h{ @$keys } = @$row;
    push @rows, \%h;
}

# print it
say dump \@rows;

saídas

[
  { description => "Boiler room", name => "B.1", sortorder => 1 },
  { description => "First office", name => 1.1, sortorder => 2 },
  { description => "Second office", name => 1.2, sortorder => 3 },
]
    
por 11.07.2016 / 22:24
0

Usando o script perl

#!/usr/bin/perl

open INFILE, "<", "inputfile";
open OUTFILE, ">", "outputfile";

$header_line = <INFILE>;
chop($header_line);
@headers = split /,/, $header_line;
foreach $header_column (@headers) {
    $header_column =~ s/^"(.*)"$/$1/;
}

while(<INFILE>) {
    chop($_); # clear the newline at the end of string
    @fields = split /,/; # split string by ,
    foreach $field (@fields) {
        $field =~ s/^"(.*)"$/$1/;
    }   
    for($i = 0; $i <= $#headers; $i++) {
        $fields[$i] = $headers[$i] . " => " . $fields[$i];
    }
    print OUTFILE "{ " . join(', ', @fields) . "},\n";

}

E com o seu inputfile

"sortorder","name","description"
"1","B.1","Boiler room"
"2","1.1","First office"
"3","1.2","Second office"

produz a saída

{ name => 'name', description => 'description', sortorder => 'sortorder' },
{ name => 'B.1', description => 'Boiler room', sortorder => '1' },
{ name => '1.1', description => 'First office', sortorder => '2' },
{ name => '1.2', description => 'Second office', sortorder => '3' },

O script mantém a ordem das colunas da primeira linha.

    
por 11.07.2016 / 18:55