Извлечь (и вывести на stdout) только определенный диапазон строк из CSV?

Извлечь (и вывести на stdout) только определенный диапазон строк из CSV?

У меня есть CSV-файл, содержащий около 1000 строк, и когда я должен его импортировать, я получаю ошибку на строке 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, описаны только столбцы.

Как можно использовать эти инструменты (или другие инструменты), чтобы просто вывести, скажем, строку 700 (или строки 702-705) из CSV-файла на 1000 строк в стандартный вывод?


EDIT: Найдено (http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.html) который csvfixимеет:

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

... однако, это действительно номер строки, а не номер ряда; так что если строка начинается со строки 406, затем прерывается на строке 407 и заканчивается на 407; тогда указанная выше команда ничего не выведет - но если вы вернетесь на одну строку назад, -if '$line == 406'то строка будет сброшена. Это тоже полезно, но все еще не является номером строки....

решение1

Команда csvfix findподдерживает дамп строки по диапазону или номеру. Следующая команда извлечет строки 3 и 4 из файла с именем file.csv.

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

Вы можете получить позицию из Text::CSV_XS Perl следующим образом:

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 не закрыта.

Связанный контент