你好,我有以下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的几种方言,并正确地处理引号字段等。