Nur einen bestimmten Zeilenbereich aus einer CSV-Datei extrahieren (und auf Standardausgabe ausgeben)?

Nur einen bestimmten Zeilenbereich aus einer CSV-Datei extrahieren (und auf Standardausgabe ausgeben)?

Ich habe eine CSV-Datei mit ca. 1000 Zeilen und dort, wo ich sie importieren soll, erhalte ich einen Fehler bei Zeile 700. Die Einträge in dieser CSV enthalten jedoch Zeilenumbrüche (und sind in Anführungszeichen gesetzt), und daher kann ich mithilfe von awkoder ähnlichem nicht wirklich schnell anzeigen, was Zeile 700 ist.

Also fand ichGibt es ein robustes Befehlszeilentool zur Verarbeitung von CSV-Dateien?, und habe sowohl csvfixals auch installiert csvkit; es scheint jedoch, dass keine dieser Anwendungen das einfache Angeben einer Zeilennummer (oder eines Zeilenbereichs) und deren Ausgabe unterstützt. Zum Beispiel:

$ 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

Ich hätte gedacht echo, dass dies das ist, was ich brauche, sobald ich angeben könnte, welche Zeile(n) wiedergegeben werden soll(en), aber wenn ich mirhttp://neilb.bitbucket.org/csvfix/manual/csvfix16/csvfix.html?unique.html, es werden nur Spalten beschrieben.

Wie könnte ich diese oder andere Tools verwenden, um beispielsweise Zeile 700 (oder die Zeilen 702–705) aus einer CSV-Datei mit 1000 Zeilen einfach auf die Standardausgabe zu übertragen?


BEARBEITEN: Gefunden (http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.html) das csvfixhat:

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

... allerdings handelt es sich hierbei tatsächlich um eine Zeilennummer und nicht um eine Zeilennummer. Wenn die Zeile also bei Zeile 406 beginnt, dann in Zeile 407 umbricht und bei 407 endet, gibt der obige Befehl nichts aus. Wenn Sie jedoch eine Zeile zurückgehen, -if '$line == 406'wird die Zeile gelöscht. Dies ist ebenfalls nützlich, ist aber dennoch keine Zeilennummer....

Antwort1

Der Befehl csvfix findunterstützt das Ausgeben einer Zeile nach Bereich oder Nummer. Der folgende Befehl extrahiert die Zeilen 3 und 4 aus einer Datei namens file.csv.

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

Antwort2

Sie können vorübergehend alle in Anführungszeichen gesetzten Zeilenumbrüche entfernen, um normale Textwerkzeuge verwenden und die Zeilenumbrüche erneut hinzufügen zu können.

Beispielsweise im Fall von doppelten Anführungszeichen:

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

Antwort3

Sie können aus Perls Text::CSV_XS wie folgt eine Position ermitteln:

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

Beachten Sie das FILENAME.csvam Ende der Zeile.

Nach erfolgreichem Parsen jeder Zeile wird dieByteVersatz.

Den Einzeiler auspacken:

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
}

Ich habe es mit diesem fehlerhaften CSS ( new.css) gefüttert:

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

Ausgabe:

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

(Wenn es vor der beschädigten Zeile mehr gute Zeilen gegeben hätte, würden mehr Byte-Offsets gedruckt. Verwenden Sie die letzte.)

Nach Byte 18 wurde also ein Fehler gefunden. Daraus lässt sich ganz einfach eine Zeilennummer ableiten: head -c 18 new.csv | wc -l, die 2 lautet (die Anzahl der guten Zeilen). Der Fehler liegt also in Zeile 3 – und das ist tatsächlich der Fall, das Anführungszeichen um r2c2 ist nicht geschlossen.

verwandte Informationen