如何从Shell中确定CSV文件中字段的数量?

3
我有一个格式良好的CSV文件,可能有标题行,也可能没有;数据可能会使用引号。我想要使用shell脚本来确定它的列数。
现在,如果我可以确定文件中没有使用引号括起来的逗号,那么以下方法似乎可行:
x=$(tail -1 00-45-19-tester-trace.csv | grep -o , | wc -l); echo $((x + 1))

但是如果我不能做出这种假设呢?也就是说,如果我不能假定逗号始终是字段分隔符,我该怎么办?
如果有帮助的话,您可以假设没有引用的引号(即在引号字符串内部)。但最好也不要做出这个假设。
3个回答

10

如果您对数据不能做出任何乐观的假设,那么在Bash中就不会有简单的解决方案。使用可能包含嵌入式换行符和嵌入式分隔符的CSV格式进行通用解析并不容易。最好不要在bash中编写代码,而是使用现有的适当CSV解析器。例如,Python在其标准库中内置了CSV解析器。

如果您可以假设没有嵌入式换行符和嵌入式分隔符,则可以使用awk按逗号拆分,这很简单:

awk -F, '{ print NF; exit }' input.csv

-F, 告诉 awk 使用逗号作为字段分隔符,而自动变量 NF 是当前行中字段的数量。

如果您想允许嵌入的分隔符,但可以假设没有嵌入的双引号,则可以在将内容传输到之前的相同 awk 之前使用简单的过滤器消除嵌入式分隔符:

head -n 1 input.csv | sed -e 's/"[^"]*"//g' | awk ...

请注意,这两个示例都使用第一行来决定字段的数量。如果输入有标题行,则应该很好地工作,因为标题不应包含嵌入式换行符。


1

计算第一行的字段数,然后验证所有行是否具有相同的数量。

 CNT=$(head -n1 hhdata.csv | awk -F ',' '{print NF}')

 cat hhdata.csv | awk -F ',' '{print NF}' | grep -v $CNT

不能处理嵌入的逗号,但如果存在则会进行高亮显示。


"第一个字段","带逗号的第二个字段名称","第三个字段"。 - einpoklum

-1
如果文件中没有双引号,则使用以下命令:
awk -F"," '{ print NF }' filename| sort -u

如果文件中的每一列都用双引号括起来,请使用以下命令:

awk -F, '{gsub(/"[^"]*"/,x);print NF}' filename | sort -u

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接