CSV から特定の範囲の行のみを抽出 (および stdout にダンプ) しますか?

CSV から特定の範囲の行のみを抽出 (および stdout にダンプ) しますか?

約 1000 行の CSV ファイルがあり、それをインポートするはずの行 700 でエラーが発生します。ただし、この CSV のエントリには改行が含まれており (引用符で囲まれています)、そのため、 またはawk同様のものを使用して行 700 が何であるかをすぐに表示することはできません。

そこで私はcsv ファイルを処理するための堅牢なコマンドライン ツールはありますか?csvfix、および の両方をインストールしましたcsvkitが、これらのアプリケーションのいずれも、行番号 (または行の範囲) を指定して出力することだけをサポートしているようです。たとえば、次のようになります。

$ 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 行目) を単純に stdout にダンプするにはどうすればよいでしょうか?


編集: 見つかりました (http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.html) には次のcsvfix機能があります:

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

... ただし、これは実際には行番号であり、行番号ではありません。したがって、行が 406 行目から始まり、407 行目に進み、407 行目で終了する場合、上記のコマンドは何も出力しません。ただし、1 行戻ると、-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 を囲む引用符は閉じられていません。

関連情報