我有以下格式的CSV数据:
S.No,Label,Customer1,Customer2,Customer3...
1,label1,Y,N,Y
2,label2,N,Y,N
...
我需要重现"标签"到"客户"的左标有 Y 的列 - 并且在标有 N 的列的左侧没有任何内容(""
)。
预期产出:
S.No,Label,Customer1,Customer1,Customer2,Customer2,Customer3,Customer3...
1,label1,label1,Y,"",N,label1,Y
2,label2,"",N,label2,Y,"",N
使用Excel打开时,它看起来像这样:
S.No Label Customer1 Customer1 Customer2 Customer2 Customer3 Customer3...
1 label1 label1 Y N label1 Y
2 label2 N label2 Y N
两个最左边的列,指的是S.No和原始"标签"列,常量。
最简单的方法是什么?我尝试了以下代码:
use strict;
use warnings;
my $nonIncludesFile = "nonIncludes.csv";
open(my $xfh, "+>", $nonIncludesFile) or warn "Unable to open $nonIncludesFile, $!";
chomp( my $header = <$xfh> );
my @names = split ",", $header;
my @names1;
my @fields;
my @fields1;
for(my $j=0; $j< scalar(@names); $j++)
{
$names1[$j] = $names[$j];
}
while(<$xfh>)
{
my $nonIncLine = $_;
$nonIncLine = chomp($nonIncLine);
@fields = split ",", $nonIncLine;
next if $. == 1; #skip the first line
for(my $i = 0; $i < scalar(@fields) -2; $i++) #Number of "customers" = scalar(@fields) -2
{
$fields1[0] = $fields[0];
$fields1[1] = $fields[1];
if('Y' eq $fields[ $i + 2 ])
{
$fields1[$i+2] = 'Y';
substr(@fields1, $i + 1, 0, $fields[1]); #insert the label to the left - HERE
}
else
{
$fields1[$i+2] = 'N';
substr(@fields1, $i + 1, 0, "");
}
}
}
print $xfh @names1;
print $xfh @fields1;
close($xfh);
但是这会引起&#34; substr在字符串之外&#34;在标有&#34; HERE&#34;。
的行我做错了什么?有没有更简单(更好)的方法呢?
答案 0 :(得分:2)
这样的事可能吗?
#!/usr/bin/perl
use strict;
use warnings;
#read the header row
chomp( my ( $sn, $label, @customers ) = split( /,/, <DATA> ) );
#double the 'customers' column headings (one is suffixed "_label")
print join( ",", $sn, $label, map { $_ . "_label", $_ } @customers ), "\n";
#iterate data
while (<DATA>) {
#strip trailing linefeed
chomp;
#extract fields with split - note breaks if you've quoted commas inline.
my ( $sn, $label, @row ) = split /,/;
print "$sn,$label,";
#iterate Y/N values, and either prints "Y" + label, or anything else + blank.
foreach my $value (@row) {
print join( ",", $value eq "Y" ? $label : "", $value ),",";
}
print "\n";
}
__DATA__
S.No,Label,Customer1,Customer2,Customer3
1,label1,Y,N,Y
2,label2,N,Y,N
假设您在字段中没有任何果味特殊字符(例如逗号),因为如果您这样做会中断,并且您可能想要考虑使用Text::CSV
。
答案 1 :(得分:1)
发布一些可用的测试数据总是比编写这样的问题
更好但是,您的数据似乎没有引用字段或转义字符,因此看起来您只需使用split
和join
来处理CSV数据
这是一个满足您要求的Perl程序示例。示例输出按原样使用您的数据。必须向后处理每行数据,以便插入不会影响尚待处理的元素的索引
use strict;
use warnings 'all';
use feature 'say';
while ( <DATA> ) {
chomp;
my @fields = split /,/;
for ( my $i = $#fields; $i > 1; --$i ) {
my $newval =
$. == 1 ? $fields[$i] :
lc $fields[$i] eq 'y' ? $fields[1] :
'';
splice @fields, $i, 0, $newval;
}
say join ',', @fields;
}
__DATA__
S.No,Label,Customer1,Customer2,Customer3...
1,label1,Y,N,Y
2,label2,N,Y,N
S.No,Label,Customer1,Customer1,Customer2,Customer2,Customer3...,Customer3...
1,label1,label1,Y,,N,label1,Y
2,label2,,N,label2,Y,,N