从CSV文件中提取前2个字段(可能包含逗号或引号)[重复]

zxlwwiss  于 5个月前  发布在  其他
关注(0)|答案(2)|浏览(69)

这个问题已经有答案了

Bash: Parse CSV with quotes, commas and newlines(11个回答)
How to extract one column of a csv file(17个回答)
What's the most robust way to efficiently parse CSV using awk?(8个回答)
上个月关门了。
我有一个包含3个或更多字段的CSV文件,我想按原样提取前2个字段,并将其保存到一个新文件。请注意,这些字段可能带引号,也可能不带引号,可能包含逗号或引号(双引号)。我想按原样提取前2个字段(无论是否带引号),并忽略第三个字段和其他字段,如果它们是。这应该从命令行完成。目前我有这个命令:

cat 1.csv | awk -F, '{print $1","$2}' > 2.csv

字符串
但如果字段中有逗号,则此操作不起作用。
字段可以是空的(不包含任何内容,甚至不包含引号)。
(我也检查了Ignoring comma in field of CSV file with awk,但那里的答案对我不起作用)

更新:这个问题是不同的,因为它要求CSV格式与原始格式相同-无论是引用或不引用字段。我有一个解决方案,我想提交。

vlurs2pr

vlurs2pr1#

假设这个输入文件包含引号字段,其中包含嵌入的引号、逗号和换行符:

$ cat file.csv
"foo,""bar""",2,3
1,"foo,bar",3
1,"foo,
bar",3

字符串
然后使用GNU awk 5.3或更高版本进行CSV处理:

$ awk --csv -v OFS=',' '{for (i=1; i<=NF; i++) { gsub(/"/,"\"\"",$i); if ($i ~ /[,\n"]/) $i="\"" $i "\"" } print $1, $2}' file.csv
"foo,""bar""",2
1,"foo,bar"
1,"foo,
bar"


CSV格式中保护字段内容所需的引号在读取输入时被剥离,因此我们必须在打印之前将它们添加回去,否则我们会得到以下输出:

$ awk --csv -v OFS=',' '{print $1, $2}' file.csv
foo,"bar",2
1,foo,bar
1,foo,
bar


这不是有效的CSV。
这就是What's the most robust way to efficiently parse CSV using awk?

bfrts1fy

bfrts1fy2#

GoCSV有一个select子命令,允许使用它来选择从指定的(或管道输入的)CSV中保留(或排除)哪些列。GoCSV在许多现代平台上是prebuilt
从这个输入CSV开始:

Col1,Col2,Col3
"foo, bar",baz,baker
"Foo, Bar",Baz,baker

字符串
你可以直接在文件上调用gocsv:

gocsv select -c 1,2 input.csv


或将CSV导入:

cat input.csv | gocsv select -c 1,2


获得:

Col1,Col2
"foo, bar",baz
"Foo, Bar",Baz


GoCSV总是将第一行解释为标题(并使用标题,以便您可以按名称调用列,如果您喜欢的话)。如果您的原始文件没有标题,您可以从cap子命令开始添加临时标题,将其导入select,然后将其导入behead子命令以删除临时标题。
添加上限:

echo \"foo, bar\",baz,baker\\n\"Foo, Bar\",Baz,Baker | gocsv cap -names Col1,Col2,Col3

Col1,Col2,Col3
"foo, bar",baz,baker
"Foo, Bar",Baz,Baker
... | gocsv select -c 1,2 | gocsv behead

"foo, bar",baz
"Foo, Bar",Baz

的字符串
cap子命令具有-default-name选项,但如果不提供至少一个带有-names的显式列名,则无法工作。

相关问题