仅从 CSV 中提取(并转储到标准输出)特定范围的行?

仅从 CSV 中提取(并转储到标准输出)特定范围的行?

我有一个大约 1000 行的 CSV 文件,在我应该导入它的地方,我在第 700 行收到错误。但是,此 CSV 中的条目包含换行符(并被引用),因此我无法真正快速使用awk或类似的方式显示第 700 行是什么。

所以我发现有没有强大的命令行工具来处理 csv 文件?,并安装了csvfixcsvkit;然而,这些应用程序似乎都不支持简单地指定行号(或行范围)并输出它们。例如:

$ csvfix help echo
echo input CSV data to output
usage: csvfix echo [flags] [file ...]
where flags are:
  -ibl      ignore blank input lines
  -sep s    specify CSV field separator character
  -rsep s   as for -sep but retain separator on output
  -osep s   specifies output separator
  -hdr s    write the string s out as a header record
  -ifn      ignore field name record
  -smq      use smart quotes on output
  -sqf fields   specify fields that must be quoted
  -o file   write output to file rather than standard output
  -skip t   if test t is true, do not process or output record

我本以为echo这就是我所需要的,只要我可以指定要回显的行,但是当我查看http://neilb.bitbucket.org/csvfix/manual/csvfix16/csvfix.html?unique.html,仅描述列。

我如何使用这些工具(或其他工具)将 1000 行 CSV 中的第 700 行(或第 702-705 行)简单地转储到标准输出?


编辑:找到(http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.htmlcsvfix具有:

csvfix find -if '$line == 407' data.csv

...但是,这确实是行号而不是行号;因此,如果该行从第 406 行开始,然后中断到第 407 行,并在第 407 行结束;那么上面的命令将不会输出任何内容 - 但如果您返回一行,-if '$line == 406'则该行将被转储。这也很有用,但仍然不是行号......

答案1

csvfixfind命令确实支持按范围或数字转储行。以下命令将从名为 file.csv 的文件中提取第 3 行和第 4 行。

csvfix find -if '$line >= 3 && $line < 5' file.csv

答案2

您可以暂时删除所有引用的换行符,以便能够使用普通文本工具并重新添加换行符。

例如,如果双引号:

gawk -v RS='"' 'NR % 2 == 0 { gsub(/\n/, "%NEWLINE%") } { printf("%s%s", $0, RT) }' file.csv > tmp.csv
head -n 700 tmp.csv | sed 's/%NEWLINE%/\n/g' > file_1-700.csv

答案3

您可以像这样从 perl 的 Text::CSV_XS 中获取位置:

perl -MText::CSV_XS -E 'open(my $fh, "<:encoding(utf8)", $ARGV[0]) or die "open: $!"; $csv = Text::CSV_XS->new({binary => 1, auto_diag => 9, diag_verbose => 1 } ); while (my $row = $csv->getline($fh)) { say tell $fh }' FILENAME.csv

请注意FILENAME.csv该行末尾的 。

成功解析每一行后,它将打印字节抵消。

拆开单线包装:

use Text::CSV_XS;
use feature 'say';
open(my $fh, '<:encoding(utf8)', $ARGV[0]) or die "open: $!";
$csv = 'Text::CSV_XS'->new({'binary' => 1, 'auto_diag' => 9, 'diag_verbose' => 1});
while (my $row = $csv->getline($fh)) {
    say tell $fh
}

我给它提供了这个错误的 CSS ( new.css):

r1c1,"r1
c2",r1c3
r2c1,"r2c2,r2c3
r3c1,r3c2,r3c3

输出:

18
# CSV_XS ERROR: 2027 - EIQ - Quoted field not terminated @ rec 1 pos 15 field 2

(如果在损坏的行之前有更多的好行,则会打印更多的字节偏移量。使用最后一行。)

所以在字节18之后,它发现了一个错误。很容易从中获得行号:head -c 18 new.csv | wc -l,其中表示 2(好行数)。所以错误出现在第 3 行——确实如此,r2c2 周围的引用没有关闭。

相关内容