【发布时间】:2012-09-04 19:54:32
【问题描述】:
我有一个类似于这个 test.csv 文件的 CSV 文件:
Header 1; Header 2; Header 3
A;B;US
C;D;US
E;F;US
G;H;FR
I;J;FR
K;L;FR
M;"String with ; semicolon";UK
N;"String without semicolon";UK
O;"String OK";
P;"String OK";
现在,我想根据标题 3 拆分这个文件。所以我想得到四个单独的 CSV 文件,一个用于“US”、“FR”、“UK”和“”。
由于我的 Linux 命令行技能非常有限(遗憾 :-( 直到现在我才使用这行代码:
awk -F\; 'NR>1{ fname="country_yearly_"$3".csv"; print >>(fname); close(fname);}' test.csv
当然,有经验的命令行用户会注意到我的问题:我的 test.csv 中的一个字段包含的行中,我用作分隔符的分号也出现在用引号标记的字段中(我由于有数百万行,因此无法确定这一点,但我对假设这一点的答案感到满意)。很遗憾,我得到了一个名为 country_yearly_ semicolon".csv 的附加文件,其中包含我的示例中的这一行。
为了解决这个问题,我在SO 上遇到了这个问题。特别是,托尔的回答似乎包含了我的问题的解决方案,它通过替换字符串中的所有分号。我相应地调整了他的代码如下:
awk -F'"' -v OFS='' '
NF > 1 {
for(i=2; i<=NF; i+=2) {
gsub(";", "|", $i);
$i = FS $i FS; # reinsert the quotes
}
print
}' test.csv > test1.csv
现在,我得到以下 test1.csv 文件:
M;"String with | semicolon";UK
N;"String without semicolon";UK
O;"String OK";
P;"String OK";
如您所见,显示了所有带引号的行,并且我的问题行也已修复,但是 a) 我实际上想要所有行,不仅是引号中的行,而且我不知道在哪个部分他的代码确实将行限制为带引号的行,b)我认为如果 test.csv 只是更改而不是将输出发送到新文件,它会更有效,但我也不知道该怎么做。
编辑回应Birei的回答:
不幸的是,我的最小示例太简单了。这是一个更新的版本:
Header 1; Header 2; Header 3; Header 4
A;B;US;
C;D;US;
E;F;US;
G;H;FR;
I;J;FR;
K;L;FR;
M;"String with ; semicolon";UK;"Yet another ; string"
N;"String without semicolon";UK; "No problem here"
O;"String OK";;"Fine"
P;"String OK";;"Not ; fine"
请注意,我的真实数据大约有 100 列和数百万行,而国家列(忽略字符串中的分号)是第 13 列。但是,据我所知,如果我不会先去掉字符串中的分号。
【问题讨论】:
标签: awk