在Bash中验证csv是否具有逗号分隔的值



你好,我有以下csv文件:

  • file1.csv:
1,2,3
asjkhfajsdkfasdj,2,iasuhdsg;ghasdgjklh
<>A<SF@!*AFSL<,ahsodgasdklgjaskd2152351235,12
hello,world,!

我想验证上面的csv文件具有以下结构(3个值(任何字符)由2个逗号分隔):

value1,value2,value3

而不是下列模式:

value1
value1,
value1,value2
value1,value2,
value1,value2,value3,
value1,value2,value3,value4

我试着使用这个命令(见链接):

CSVcnt=`awk 'BEGIN{FS=","}END{print NF}' $csv_file`
echo "CSVcnt = $CSVcnt"

上面的命令将返回正确的3。


但是让我们考虑以下场景,使用以下命令:

  • file2.csv
1,2,3,4,5,6,7,8,9,10
1,2,3
1,2,3
1,2,3

将返回3,这是不正确


  • file3.csv
1,2,3
1,2,3
1,2,3
1,2,3,4,5,6,7,8,9,10

将返回10,即正确的


  • file4.csv
1,2,3
1,2,3
1,2,3,4,5,6,7,8,9,10
1,2,3,4

将返回4,这是不正确

因此,看起来我使用的awk命令仅基于最后一行。您能否建议是否有一种方法可以使用awk命令返回在整个文件中找到的最大数量?请注意,我不喜欢使用REGEX,如果可能的话也不喜欢使用for循环。(每个csv将有10K到40K行)

如果您只想获得NF的最大值,那么您可以这样做:

awk -F ',' 'NF > maxNF {maxNF = NF} END {print maxNF+0}' file.csv

如果你想计数字段

awk -F, '{a[NF]++} END {for (e in a) {print e ":" a[e]}}' file.csv

产生类似

的东西
3:2
4:1
10:1

为你的例子

1,2,3
1,2,3
1,2,3,4,5,6,7,8,9,10
1,2,3,4

如果您不担心引号字段(可以包含换行符以及不是字段分隔符的字面逗号),可以尝试两遍解决方案。

awk -F, 'BEGIN { OFS=":" }
NR==FNR { ++n[NF]; next }
FNR == 1 { for(k in n) if (n[k] > m) { m=n[k]; f=k } }
NF != k { print FILENAME, FNR, $0 }' file.csv file.csv

打印所有与"normal"字段数不同的行

如果还想打印最后一个字段为空的行,可以添加

(!$NF) ||

在最后一个条件之前

一个合适的解决方案很难单独在Awk中完成,但在Python中非常简单;标准库中的csv模块处理CSV的几种方言,并正确地处理引号字段等。

相关内容

  • 没有找到相关文章

最新更新