如何从 shell 中确定 CSV 中的字段数?

How can I determine the number of fields in a CSV, from the shell?

我有一个 well-formed CSV 文件,它可能有也可能没有 header 行;并且可能有也可能没有引用数据。我想使用 shell.

确定其中的列数

现在,如果我可以确定文件中没有引号逗号,则以下内容似乎有效:

x=$(tail -1 00-45-19-tester-trace.csv | grep -o , | wc -l); echo $((x + 1))

但是如果我不能做出那个假设怎么办?也就是说,如果我不能假设逗号始终是字段分隔符怎么办?那我该怎么做呢?

如果有帮助,您可以假设没有引号(即引号字符串之间的 \"s);但最好也不要做那个。

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

如果您可以假设没有嵌入式换行符和嵌入式分隔符,那么使用 awk 以逗号分隔就很简单了:

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

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

如果你想允许嵌入分隔符,但你可以假设没有嵌入双引号,那么你可以用一个简单的过滤器消除嵌入的分隔符,然后再传输到与之前相同的 awk:

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

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

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

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

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

无法处理嵌入的逗号,但会突出显示它们是否存在

如果文件没有双引号则使用下面的命令:

awk -F"," '{ print NF }' filename| sort -u

如果文件的每一列都用双引号括起来,那么使用下面的命令:

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