我有一组需要修改的4个大量CSV文件。我需要做的是匹配这个表达式/^(.*),,/
复制原子然后将它添加到每个后续行,直到原子再次匹配。然后我需要冲洗并重复直到文件的末尾(每个文件中有大约25k行)。最后,我需要回过头去掉第一个原子。
如果有可能,我想用sed。我尝试用vim做这个但是无法正确使用正则表达式。任何帮助将不胜感激。一个例子如下所示:
之前:
0917,,
,882-1273,1
,95F 9475,1
,276-080,1
,40K 0080,1
,275-690A,1
,TX-2311,3
,TX-3351,4
,B-07432,1
,B-6901,1
,23-753,1
,02F 4307,1
,5.1K QBK-ND,1
,0944-026,1
,0944-027,1
,0944-004,1
,0944-056,1
,0944-057,1
,0944-082,1
,0944-024,1
,0944-025,1
,0944-102,4
,LOR 102,1
0918,,
,CJ1085,1
,1352-152,4
,DMS3102A-18-,1
,6-32 KEP,7
,6-32 X 3/4,4
,6-32X1/2,4
,1251-102,8
,Oct-32,4
,10-32 SAE,8
后:
0917,882-1273,1
0917,95F 9475,1
0917,276-080,1
0917,40K 0080,1
0917,275-690A,1
0917,TX-2311,3
0917,TX-3351,4
0917,B-07432,1
0917,B-6901,1
0917,23-753,1
0917,02F 4307,1
0917,5.1K QBK-ND,1
0917,0944-026,1
0917,0944-027,1
0917,0944-004,1
0917,0944-056,1
0917,0944-057,1
0917,0944-082,1
0917,0944-024,1
0917,0944-025,1
0917,0944-102,4
0917,LOR 102,1
0918,CJ1085,1
0918,1352-152,4
0918,DMS3102A-18-,1
0918,6-32 KEP,7
0918,6-32 X 3/4,4
0918,6-32X1/2,4
0918,1251-102,8
0918,Oct-32,4
0918,10-32 SAE,8
答案 0 :(得分:3)
正如我在前一个问题中指出的那样,我发现Perl更容易:
#!/usr/bin/perl
use strict;
use warnings;
my $prefix = q{};
while ( <> ) {
last unless /\S/;
if ( /^(.+),,$/ ) {
$prefix = $1;
next;
}
print $prefix, $_;
}
答案 1 :(得分:2)
程序(python)
import csv
infile=file("in","r")
outfile=file("out","w")
reader = csv.reader(infile , dialect='excel')
writer = csv.writer(outfile , dialect='excel')
current_header=""
for inrow in reader:
if len(inrow[0].strip()) != 0:
current_header = inrow[0]
continue
writer.writerow([current_header]+inrow[1:])
infile.close()
outfile.close()
print "done"
输入
0917,,
,882-1273,1
,95F 9475,1
,276-080,1
,40K 0080,1
,275-690A,1
,TX-2311,3
,TX-3351,4
,B-07432,1
,B-6901,1
,23-753,1
,02F 4307,1
,5.1K QBK-ND,1
,0944-026,1
,0944-027,1
,0944-004,1
,0944-056,1
,0944-057,1
,0944-082,1
,0944-024,1
,0944-025,1
,0944-102,4
,LOR 102,1
0918,,
,CJ1085,1
,1352-152,4
,DMS3102A-18-,1
,6-32 KEP,7
,6-32 X 3/4,4
,6-32X1/2,4
,1251-102,8
,Oct-32,4
,10-32 SAE,8
输出
0917,882-1273,1
0917,95F 9475,1
0917,276-080,1
0917,40K 0080,1
0917,275-690A,1
0917,TX-2311,3
0917,TX-3351,4
0917,B-07432,1
0917,B-6901,1
0917,23-753,1
0917,02F 4307,1
0917,5.1K QBK-ND,1
0917,0944-026,1
0917,0944-027,1
0917,0944-004,1
0917,0944-056,1
0917,0944-057,1
0917,0944-082,1
0917,0944-024,1
0917,0944-025,1
0917,0944-102,4
0917,LOR 102,1
0918,CJ1085,1
0918,1352-152,4
0918,DMS3102A-18-,1
0918,6-32 KEP,7
0918,6-32 X 3/4,4
0918,6-32X1/2,4
0918,1251-102,8
0918,Oct-32,4
0918,10-32 SAE,8
玩得开心
答案 2 :(得分:1)
由于sed的语法含糊不清,你不是日复一日地使用,而不是谈论你的同事,这段代码很难维护。 Perl / awk解决方案是首选。
无论如何,here是我见过的最好的手册。
祝你好运 迪马答案 3 :(得分:1)
Perl可能更容易:
#!/usr/bin/perl -w
$filename = $ARGV[0];
open FILE, "<", $filename or die $!;
while (<FILE>) {
if(/^(.*),,/) {
$prefix = $_;
$prefix =~ s/,//g;
$prefix =~ s/\s+//g;
next;
}
s/^,/$prefix,/g;
print $_;
}
close FILE;
答案 4 :(得分:0)
以下是awk的解决方案:
awk -F, '{ if ($1 != "") prefix=$1; else printf "%s%s\n", prefix,$0 }' myfile.csv
答案 5 :(得分:0)
这是一个用Perl编写的全功能示例,它使用了Perl 5.10的新功能;
#!/usr/bin/perl
use strict;
use warnings;
use feature qw'switch say';
my $append;
while( <> ){
given( $_ ){
when( /^$/ ){
# handle empty line
say STDERR '#';
}
# handle lines that start with "#"
when( /^\s*[#](.*)/s ){
print STDERR '# comment:', $1;
}
# handle lines that end with two commas
when( /(.+),,\s*$/ ){
$append = $1;
}
# handle lines that start with a comma
when( /^,/ ){
die unless defined $append;
print $append, $_;
}
}
}
输入
0917,,
,882-1273,1
,95F 9475,1
,276-080,1
,40K 0080,1
,275-690A,1
,TX-2311,3
# ignore
# ignore this too
,TX-3351,4
,B-07432,1
,B-6901,1
,23-753,1
,02F 4307,1
,5.1K QBK-ND,1
,0944-026,1
,0944-027,1
,0944-004,1
,0944-056,1
,0944-057,1
,0944-082,1
,0944-024,1
,0944-025,1
,0944-102,4
,LOR 102,1
0918,,
,CJ1085,1
,1352-152,4
,DMS3102A-18-,1
,6-32 KEP,7
,6-32 X 3/4,4
,6-32X1/2,4
,1251-102,8
,Oct-32,4
,10-32 SAE,8
输出
#
# comment: ignore
# comment: ignore this too
0917,882-1273,1
0917,95F 9475,1
0917,276-080,1
0917,40K 0080,1
0917,275-690A,1
0917,TX-2311,3
0917,TX-3351,4
0917,B-07432,1
0917,B-6901,1
0917,23-753,1
0917,02F 4307,1
0917,5.1K QBK-ND,1
0917,0944-026,1
0917,0944-027,1
0917,0944-004,1
0917,0944-056,1
0917,0944-057,1
0917,0944-082,1
0917,0944-024,1
0917,0944-025,1
0917,0944-102,4
0917,LOR 102,1
0918,CJ1085,1
0918,1352-152,4
0918,DMS3102A-18-,1
0918,6-32 KEP,7
0918,6-32 X 3/4,4
0918,6-32X1/2,4
0918,1251-102,8
0918,Oct-32,4
0918,10-32 SAE,8
答案 6 :(得分:0)
这是一个sed解决方案。这不是最干净的,我确信有更好的音译这两行的方法,但我觉得这很有趣。 (实际上,我会使用Perl解决方案,但是我发布了这个新颖的内容,并希望看到改进。)
sed -e '/,,/{s/,,//; h; d;}' -e 'G' -e 's/\(.*\)\n\(.*\)/\2\1/'