如何从CSV数据拆分和填充值?

时间:2019-02-06 14:16:15

标签: perl csv parsing

如何在某些列中按换行符(\ n)分割值,提取到新行并填充其他列

我的示例CSV数据(data.csv)

No,Email,IP,Service,Comment
1,test@email.com,192.168.10.109,FTP
HTTP
HTTPS,,
2,webmaster@email.com,192.168.10.111,SFTP
SNMP,,
3,admin@email.com,192.168.10.112,HTTP,,

“服务”列中有多个值,用新行分隔。

我要提取它并在其他行中填充其他值,如下所示。

1,test@email.com,192.168.10.110,FTP,,
1,test@email.com,192.168.10.110,HTTP,,
1,test@email.com,192.168.10.110,HTTPS,,
2,webmaster@email.com,192.168.10.111,SFTP,,
2,webmaster@email.com,192.168.10.111,SNMP,,
3,admin@email.com,192.168.10.112,HTTP,,

我尝试使用Text :: CSV进行解析,我只能拆分多个ip和服务,但是我不知道要像上面的示例那样填充其他值。

#!/usr/bin/perl
use Text::CSV;
my $file = "data.csv";
my @csv_value;
open my $fh, '<', $file or die "Could not open $file: $!";
my $csv = Text::CSV->new;
my $sum = 0;
open(my $data, '<:encoding(utf8)', $file) or die "Could not open '$file' $!\n";
while (my $fields = $csv->getline( $data )) {
    push @csv_value, $fields;
}
close $data;

在此先感谢您提供的帮助。

2 个答案:

答案 0 :(得分:1)

扩大我的评论

perl -ne 'if (!/^\d/){print "$line$_";} else {print $_;} /(.*,).*/; $line=$1;' file1

使用perl command line options

e = inline command
n = implicit loop, i.e. for every line in the file do the script

文件的每一行现在都在$ _默认变量中

if (!/^\d/){print "$line$_";} - if the line does not start with a digit print the $line (more later) variable, followed by default variable which is the line from the file

else {print $_;} - else just print the line

现在,在执行此操作后,如果该行与任何字符匹配,然后跟一个逗号,然后匹配任何东西,请用正则表达式括起来将其放入$ 1中。因此,对于第一行,$ 1将为“ 1,test @ email.com,192.168.10.109,”

/(.*,).*/; $line=$1;

因为我们在打印第一行之后执行此操作,所以$ line始终是前一个完整行。

答案 1 :(得分:0)

您输入的CSV损坏。我建议修复发电机。

如果使用正确格式的输入CSV,则您必须在Text::CSV中启用binary选项,因为您的数据包含非ASCII字符。

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

use Text::CSV;

# input has non-ASCII characters
my $csv_in  = Text::CSV->new({ binary => 1 });
my $csv_out = Text::CSV->new();
$csv_out->eol("\n");

while (my $row = $csv_in->getline(\*STDIN)) {
    for my $protocol (split("\n", $row->[3])) {
        $row->[3] = $protocol;
        $csv_out->print(\*STDOUT, $row);
    }
}

exit 0;

使用固定的输入数据进行测试:

$ cat dummy.csv
No,Email,IP,Service,Comment
1,test@email.com,192.168.10.109,"FTP
HTTP
HTTPS",,
2,webmaster@email.com,192.168.10.111,"SFTP
SNMP",,
3,admin@email.com,192.168.10.112,HTTP,,

$ perl dummy.pl <dummy.csv 
No,Email,IP,Service,Comment
1,test@email.com,192.168.10.109,FTP,,
1,test@email.com,192.168.10.109,HTTP,,
1,test@email.com,192.168.10.109,HTTPS,,
2,webmaster@email.com,192.168.10.111,SFTP,,
2,webmaster@email.com,192.168.10.111,SNMP,,
3,admin@email.com,192.168.10.112,HTTP,,
相关问题