我有一个类似于此 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 列。但是,据我所知,如果我不这样做,我就不能使用它是第 13 列的事实。不要先去掉字符串中的分号。