如何在带有逗号的文本字段的大型csv中使用awk分隔符

如何在带有逗号的文本字段的大型csv中使用awk分隔符,awk,Awk,我有一个.csv,有470列和数万行产品,其中许多带有包括逗号在内的文本字符串,这会导致我的awk语句爆炸并写入错误的列,从而损坏我的数据。以下是我使用的语句: 输入示例: LDB0010-300,"TIMELESS DESIGN: Classic, Elegant, Beautiful",Yes,1,Live,... LDB0010-400,"CLASSIC DESIGN: Contemporary look",No,0,Not Live,... LDB

我有一个.csv,有470列和数万行产品,其中许多带有包括逗号在内的文本字符串,这会导致我的awk语句爆炸并写入错误的列,从而损坏我的数据。以下是我使用的语句:

输入示例:

LDB0010-300,"TIMELESS DESIGN: Classic, Elegant, Beautiful",Yes,1,Live,...
LDB0010-400,"CLASSIC DESIGN: Contemporary look",No,0,Not Live,...
LDB0010-500,"Everyone should wear this, almost!",Yes,0,Not Live,...
代码:

cat products.csv | sed-e's/,/@/g'| awk-F,'NR>1{$308=“LIVE”;$310=“LIVE”;$467=0;print$0}OFS=,| sed-e's/@,/g'
当前输出,与写入错误列的数据错误:

LDB0010-300,"TIMELESS DESIGN: Classic",LIVE, Beautiful",Yes,1,Live,...
LDB0010-400,"CLASSIC DESIGN: Contemporary look",No,0,0,...
LDB0010-500,"Everyone should wear this",LIVE,Yes,0,Not Live,...

在仔细研究数据时,我注意到在带有文本描述的单元格中,逗号后面总是跟一个空格,而用作分隔符的逗号后面没有空格。所以我采取的方法是用“@”替换逗号空间,运行我的awk语句来设置这些列的值,然后从“@”替换回逗号空间。这一切看起来都很好,直到我打开电子表格,注意到有许多行的值写入了错误的列。有谁知道更好的方法来防止这些爆发吗?

您发布的示例数据不会重现您报告的症状以及您提供的代码。最简单的解释是,您观察到带空格的逗号总是字段内部的,而其他逗号不是字段内部的,这实际上是不正确的。这应该很容易检查

sed's/,/@/g'products.csv|awk-F,{a[NF]+}END{for(a中的n)print n,a[n]}
如果您没有得到一行列数和行数完全正确的输出,则可以看出您的
sed
技巧工作不正常。(另请注意

无论如何,这里有一个简单的Python重构,希望它足够明显。Python CSV库知道如何处理带引号的字段,因此它只会在双引号之外的逗号上拆分

!/usr/bin/env python3
导入csv
导入系统
w=csv.writer(sys.stdout)
对于sys.argv[1:]中的文件:
打开(文件,换行符=“”)作为输入文件:
r=csv.reader(输入文件)
对于r中的行:
第[307]行=“现场”
第[309]行=“现场”
第[466]行=0
w、 writerow(世界其他地区)
请注意Python的索引是如何从零开始的,而Awk从一开始计算字段

你会像这样运行它

python3 this_script.py products.csv
另请参见Python,了解您可能要使用的各种选项

上述方法读取所有输入文件并将输出写入标准输出。如果您只想读取单个输入文件并写入其他文件,则可以简化为

!/usr/bin/env python3
导入csv
导入系统
将open(sys.argv[1],换行符=“”)作为输入文件,将open(sys.argv[2],'w',换行符=“”)作为输出文件:
r=csv.reader(输入文件)
w=csv.writer(输出文件)
header=True
对于r中的行:
如果不是标题:#不要弄脏第一行
第[307]行=“现场”
第[309]行=“现场”
第[466]行=0
w、 writerow(世界其他地区)
标题=假
你会把它当作

python3 thisscript.py input.csv output.csv

我绝对不喜欢将输出文件指定为命令行参数(我们应该有一个选项)但是对于一次性的快速测试,我想这是可以接受的。

应该为您指出正确的方向。这是否回答了您的问题?如果您的CSV实际上不是有效的CSV,很难说。如果是有效的CSV,请使用带有适当CSV解析器的语言;许多人发现Python的CSV支持功能多样且强大,而且该语言本身很容易学习,足以取代传统的CSV两个Awk语句。如果您感兴趣,我有一个支持正确拆分csv数据的Awk克隆(改用tcl)。@Shawn
tawk
是Awk变体(如gawk、mawk和nawk)的名称,请参阅,因此在您的软件中使用名称
tawk
,可能会引起一些混淆。有gawk扩展库(请参阅)要处理各种格式(例如json和xml),我希望使用CSV()将很快提供给任何想要安装外部软件包的人。谢谢…我知道数据示例只是一个示例,实际的工作表有数百列和数万行。它只是为了显示我看到的内容。我不懂python,但我确信深入研究一下您的python解决方案,它似乎是最优雅的。不是吗感谢分享并展示如何调用它。问题:它是将编辑的行直接写回原始的输入it文件?还是输出不同的文件名?或者更确切地说,是吗?这一行只打印到标准输出(注意
sys.stdout
),但用open将writer更改为
('newfile.csv','w')作为outputfile:
并缩进脚本的其余部分,添加
w=csv.writer(outputfile)
在带有块的
中。我用更详细的说明更新了答案。实际上,当我创建一个output.csv文件供它去…时,不再给我错误,但没有写入任何内容…
-rw-rw-r--1 admin admin 0 Sep 4 14:13 output.csv对我有效(调整了索引):…如果您的行不够长,您将得到一个带有
索引器的回溯,以及一个空的或不完整的输出文件。好的,我看到我的最后一行错了。它现在正在工作。还有一个问题,它会覆盖列标题。有没有办法防止这种情况发生???