Tengo un archivo CSV de aproximadamente 1000 filas, y donde se supone que debo importarlo, aparece un error en la fila 700. Sin embargo, las entradas en este CSV contienen nuevas líneas (y están entrecomilladas) y, por lo tanto, no puedo usarlas rápidamente awk
o similar para mostrar cuál es la fila 700.
Entonces encontré¿Existe una herramienta sólida de línea de comandos para procesar archivos csv?, e instalé ambos csvfix
y csvkit
; sin embargo, parece que ninguna de estas aplicaciones admite simplemente especificar un número de fila (o un rango de filas) y generarlas. Por ejemplo:
$ 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
Habría pensado echo
que es lo que necesito, tan pronto como pude especificar qué fila(s) se va a repetir, pero cuando mirohttp://neilb.bitbucket.org/csvfix/manual/csvfix16/csvfix.html?unique.html, solo se describen las columnas.
¿Cómo podría usar estas herramientas, u otras herramientas, para simplemente volcar, por ejemplo, la fila 700 (o las filas 702-705) de un CSV de 1000 filas a la salida estándar?
EDITAR: Encontrado (http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.html) que csvfix
tiene:
csvfix find -if '$line == 407' data.csv
... sin embargo, este es de hecho el número de línea y no el número de fila; entonces, si la fila comienza en la línea 406, luego pasa a la línea 407 y termina en 407; entonces el comando anterior no generará nada, pero si retrocede una línea, -if '$line == 406'
la fila se descarta. Esto también es útil, pero todavía no es un número de fila...
Respuesta1
El comando csvfix find
admite el volcado de una fila por rango o número. El siguiente comando extraería las líneas 3 y 4 de un archivo llamado file.csv.
csvfix find -if '$line >= 3 && $line < 5' file.csv
Respuesta2
Puede eliminar temporalmente todas las nuevas líneas entre comillas para poder utilizar las herramientas de texto normales y volver a agregar las nuevas líneas.
Por ejemplo, en caso de comillas dobles:
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
Respuesta3
Puede obtener una posición del Text::CSV_XS de Perl de esta manera:
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
Tenga en cuenta el FILENAME.csv
al final de la línea.
Después de analizar con éxito cada fila, imprimirá elbytecompensar.
Desembalaje del resumen:
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
}
Le alimenté este CSS defectuoso ( new.css
):
r1c1,"r1
c2",r1c3
r2c1,"r2c2,r2c3
r3c1,r3c2,r3c3
Producción:
18
# CSV_XS ERROR: 2027 - EIQ - Quoted field not terminated @ rec 1 pos 15 field 2
(Si hubiera más filas buenas antes de la corrupta, se imprimirían más compensaciones de bytes. Utilice la última).
Entonces, después del byte 18, encontró un error. Es bastante fácil obtener un número de línea a partir de eso: head -c 18 new.csv | wc -l
, que dice 2 (el número de líneas buenas). Entonces el error está en la línea 3, y de hecho lo está, la cita alrededor de r2c2 no está cerrada.