我有一个CSV文件,有些字段是空的。
样本数据
ItemA,5,4,3,2,1
ItemB,7,,,2,4
ItemC,,,,2,
ItemD,,3,,,
我想在文件上传递一个perl一行,这将插入一个字符串,在每个逗号之间插入NULL,或者在最后一个逗号之后,如果之后没有值。
所以在正则表达式之后,数据应如下所示:
ItemA,5,4,3,2,1
ItemB,7,NULL,NULL,2,4
ItemC,NULL,NULL,NULL,2,NULL
ItemD,NULL,3,NULL,NULL,NULL
我不知道如何创建此正则表达式,我们非常感谢您的帮助。谢谢。
答案 0 :(得分:3)
简单,使用正面的lookbehind和lookahead断言,如下所示。
$ perl -pe 's/(?<=,)(?=,|$)/NULL/g' file
ItemA,5,4,3,2,1
ItemB,7,NULL,NULL,2,4
ItemC,NULL,NULL,NULL,2,NULL
ItemD,NULL,3,NULL,NULL,NULL
(?<=,)
只需看看所有逗号。也就是说,它断言匹配必须以逗号开头。
(?=,|$)
并且匹配后紧跟逗号或线锚的结尾。因此,它匹配所有逗号之间存在的所有边界以及最后一个逗号旁边的逗号。
用NULL
字符串替换匹配的边界将为您提供所需的输出。
答案 1 :(得分:2)
我不会使用正则表达式。使用核心模块Text::ParseWords
:
perl -MText::ParseWords -lne'
@w = parse_line (",", 1, $_);
print join ",", map { (length) ? $_ : "NULL" } @w
' file
ItemA,5,4,3,2,1
ItemB,7,NULL,NULL,2,4
ItemC,NULL,NULL,NULL,2,NULL
ItemD,NULL,3,NULL,NULL,NULL
或者使用split
的可选第三个参数。
perl -lne'
@F = split ",", $_, -1;
print join ",", map { (length) ? $_ : "NULL" } @F
' file
ItemA,5,4,3,2,1
ItemB,7,NULL,NULL,2,4
ItemC,NULL,NULL,NULL,2,NULL
ItemD,NULL,3,NULL,NULL,NULL
答案 2 :(得分:2)
这是一个带有正则表达式的解决方案:
$ perl -pe 's/,(?=,)|,$/,NULL/g' file.csv
ItemA,5,4,3,2,1
ItemB,7,NULL,NULL,2,4
ItemC,NULL,NULL,NULL,2,NULL
ItemD,NULL,3,NULL,NULL,NULL
即。匹配逗号,后跟逗号(,(?=,)
)或逗号末尾的逗号(,$
),并将匹配的逗号替换为,NULL
。
编辑:正如 Casimir et Hippolyte 所指出的,s/,(?=,|$)/,NULL/g
更简单。
(匹配逗号后紧跟另一个逗号或行结束)。
答案 3 :(得分:0)
您可以使用:
#!/usr/bin/perl
use strict;
use warnings;
my $fpath = "./data.txt";
open(my $fh, '<', $fpath) or die "*** Cannot open $fpath:\n$!\n";
while ( <$fh> ) {
while(1) { last if ( $_ !~ s/,\s*,/,NULL,/g ) }
$_ =~ s/,\s*$/,NULL/g;
print $_ . "\n";
}