字数统计命令为CSV文件返回错误的行数

2nc8po8w  于 2023-05-20  发布在  其他
关注(0)|答案(4)|浏览(108)

我正在运行以下命令来计算CSV文件中的行数:

wc -l filename.csv

有时行计数是正确的,而其他时候它比实际计数少1。所有文件的格式都相同,标题行也相同。我首先怀疑的是标题行,但该命令似乎无法区分标题行和其他行。文件以相同的编码utf-8保存。
这是CSV文件的格式问题和/或wc命令的细微差别吗?

9rbhqvlz

9rbhqvlz1#

使用csvkit附带的真实的CSV解析器:

$ cat file.csv
col1,col2,col3
aa,bb,"c
c"
$ csvstat --count file.csv
1

可以安装在所有操作系统上,具有:

pip install csvkit

Debian及其衍生产品:

$ apt show csvkit
[...]
Package: csvkit
Architecture: all
Version: 1.0.6-1
Priority: optional
Depends: python3:any, python3-csvkit
Size: 27172
Homepage: https://github.com/wireservice/csvkit
Description-en: command-line tools for working with CSV
 csvkit is a suite of command-line tools for converting to and working with
 CSV, the king of tabular file formats.
 .
 It is inspired by pdftk, gdal and the original csvcut tool by Joe Germuska and
 Aaron Bycoffe.
 .
 If you need to do more complex data analysis than csvkit can handle, use
 agate.
 .
 This package provides the command-line tools.
nhn9ugyo

nhn9ugyo2#

假设你有:

cat file
Côl 1,Cól 2,Cöl 3
1,2,æ
3,4,ç
5,6,"new 
line"

此CSV文件有一个标题和一个带新行的字段。如果在该文件上运行wc -l,它会计算遇到的\n的数量--即使是在字段中。如果在最后一行上有一个终止符\n,则可能会使计数值减少1。
你只能在以下情况下使用wc -l:1)你知道没有带换行符的字段,2)在最后一行的末尾有一个正确的终止符\n。授予--大多数CSV文件都符合条件,直到它们不符合条件。
您可以使用Ruby来计算CSV文件中解析的实际数据:

ruby -r csv -e '
puts CSV.parse($<.read, **{:headers=>false}).count
' file

图纸:

4

如果你不想把标题算作一个数据行:

ruby -r csv -e '
puts CSV.parse($<.read, **{:headers=>true}).count
' file
# 3

或者使用Miller

mlr --csv count file
count
3

米勒和Ruby CSV都可以工作,不管字段中是否有\n或最后一行是否有终止\n。即使一个字段中有一个\n,米勒和Ruby都将其视为一条记录。

qpgpyjmq

qpgpyjmq3#

假设:

  • OP的问题是偶尔文件在最后一行末尾缺少\n
  • .csv数据字段不包括嵌入式换行符(\n);否则,计数将返回文件中的 * 行 * 数,而不是文件中的 * 记录 * 数

设置一些测试文件:

$ printf "a\nb\nc"   > file1            # no \n on the last line
$ printf "a\nb\nc\n" > file2

$ od -c file1
0000000   a  \n   b  \n   c  
0000005                      ^^-- terimination is missing

$ od -c file2
0000000   a  \n   b  \n   c  \n
0000006                      ^^-- terminate last line

我们可以看到,wc -l 'misses'了file1的最后一行:

$ wc -l file1
2 file1

$ wc -l file2
3 file2

一种适用于两个文件的awk方法:

$ awk 'END {print NR}' file1
3

$ awk 'END {print NR}' file2
3

另一种方法是让OP遍历并将\n附加到缺少\n的文件的最后一行。
bash insure last line has linefeed上进行网络搜索将是开始寻找解决方案的好地方。

brgchamk

brgchamk4#

也许这样可以

for __ in $'col1,col2,col3\naa,bb,"c\nc"'  
           $'col1,col2,col3\naa,bb,"c\nc"\n' 
           $'a\nb\nc'
           $'a\nb\nc\n'  
           $'Côl 1,Cól 2,Cöl 3\n1,2,æ\n3,4,ç\n5,6,"new\nline"' ; do

     printf '----\n|%s|\n-----\n :: %s\n' "$__" "$( 

     printf '%s' "$__" |
gawk -F',' 'BEGIN {   OFS = "\13 |" 
             }     {  ___ += ($NF ~ /"/) - ($1 ~ /"/)
                     ____ += length($0)
                    _____ +=  match($0, /$/) - 1 
 } END { 
     print __ = "", ("gross NR :: ") (_ = NR), 
                    (  "adj NR :: ")((_-= __ = RT == __) - ___), 
                    (   "chars :: ") (_ + ____),
                    (   "bytes :: ") (_ + _____) }' )"
done
----
|col1,col2,col3
aa,bb,"c
c"|
-----
 :: 
     |gross NR :: 3
                    |adj NR :: 1
                                 |chars :: 26
                                              |bytes :: 26
----
|col1,col2,col3
aa,bb,"c
c"
|
-----
 :: 
     |gross NR :: 3
                    |adj NR :: 2
                                 |chars :: 27
                                              |bytes :: 27
----
|a
b
c|
-----
 :: 
     |gross NR :: 3
                    |adj NR :: 2
                                 |chars :: 5
                                             |bytes :: 5
----
|a
b
c
|
-----
 :: 
     |gross NR :: 3
                    |adj NR :: 3
                                 |chars :: 6
                                             |bytes :: 6
----
|Côl 1,Cól 2,Cöl 3
1,2,æ
3,4,ç
5,6,"new
line"|
-----
 :: 
     |gross NR :: 5
                    |adj NR :: 3
                                 |chars :: 44
                                              |bytes :: 49

字符/字节计数与gnu-wc:::

printf '%s' "$__" | gwc -cm
26      26
 27      27
  5       5
  6       6
 44      49

相关问题