如何将行合并到csv文件中

时间:2017-12-11 15:54:49

标签: perl csv cgi

我有一个带有多行的csv文件,其中第一个字段是重复的,而从其他字段只有一行实际填充(并且总是不同) 我需要编写一个将这些行合并为一个的perl CGI csv文件类似于下面的示例

aaaa,3
aaaa,,5
aaaa,,,1
aaaa,,,,3
bb,2
bb,,4
bb,,,,,,,,,,6
cc,,,,,,5
dd,5

我想要输出的内容应该是:

aaaa,3,5,1,3
bb,2,4,,,,,,,,6
cc,,,,,,5
dd,5

我对perl语言很新,但是从我做过的一些研究中我认为使用哈希似乎是要走的路,但我仍然没有完全了解这些是如何工作的,请记住我需要在perl cgi中使用它,所以一个命令行不会帮助我

所以我从另一篇帖子here

中抓取这段代码
open my $ifh, '<', "input_file" or die $!;
open my $ofh, '>', "output_file" or die $!;
while (<$ifh>) {
    chomp;
    my @F = split /,/;
    my $key = shift @F;
    push @{$hash{$key}}, @F;
}

foreach (sort keys %hash) {
    print $ofh "$_," . join (',', @{$hash{$_}}) . "\n";
}

close $ifh;
close $ofh;

但它只是在重复的同一行添加字段,我需要在实际的未定义字段中写入

3 个答案:

答案 0 :(得分:3)

关于合并来自不同行的值的一点对我感兴趣,足以让我们去了解它。这就是我所做的。其他人可能能够改善我的解决方案。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
1<input type="checkbox" class="checkoption" /> 2
<input type="checkbox" class="checkoption" /> 3
<input type="checkbox" class="checkoption" /> 4
<input type="checkbox" class="checkoption" /> everything
<input type="checkbox" class="checkoption" id="everythingbox" checked/>

我得到的输出是:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my %data;

while (<DATA>) {
  chomp;
  my ($key, @values) = split /,/;

  if ($data{$key}) {
    # It seems we can be sure that the new value
    # we're adding will be the last element on the line.
    $data{$key}[$#values] = $values[$#values];
  } else {
    $data{$key} = \@values;
  }
}

for my $k (sort keys %data) {
  say join ',', $k, map { $_ // '' } @{$data{$k}};
}

__DATA__
aaaa,3
aaaa,,5
aaaa,,,1
aaaa,,,,3
bb,2
bb,,4
bb,,,,,,,,,,6
cc,,,,,,5
dd,5

将此转换为使用CGI进行输入和输出留给读者练习: - )

答案 1 :(得分:2)

answer from Dave Cross 非常好,但它依赖于每一行数据比同一密钥的所有数据都长,这不是你的问题所确定的

这是一个非常类似的程序来修复它,并且还跟踪键在源数据中出现的顺序,以便它可以在输出上再现

该程序期望输入CSV文件的路径作为命令行上的参数,并将输出打印到STDOUT。您可以在命令行上重定向输出

将此作为CGI应用程序编写是一个非常广泛的问题。如果你遇到困难,你需要尽你所能并在这里询问具体的问题

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ...
    ipaddress = models.CharField(default="0.0.0.0", max_length=30)

输出

use strict;
use warnings 'all';

my ( @keys, %data );

while ( <> ) {
    next unless /\S/;
    chomp;
    my @newline = split /,/;
    my $key = $newline[0];

    if ( my $line = $data{ $key } ) { # Update any previously-blank fields

        for my $i ( 0 .. $#newline ) {

            $line->[$i] = $newline[$i] unless length $line->[$i] // '';
        }
    }
    else { # Build the first instance of this key

        $data{ $key } = \@newline;
        push @keys, $key;
    }
}

print join( ',', @{ $data{$_} } ), "\n" for @keys;

答案 2 :(得分:0)

我会像这样修改你的代码:

$#F

(0..$#F)是最后一个元素的数组地址,因此$hash{$key}是@F中地址的范围。这允许您将@F中的元素分配到另一个数组的相同地址(在这种情况下,${$hash{$key}}[$i]是一个匿名数组,也就是一个arrayref,$hash{$key}->[$i] //= $F[$i]访问该数组的$ i元素)

{{1}}表示只有在尚未定义元素的情况下才会分配。