Извлечь (и сбросить в 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 строк в stdout?


EDIT: найдено ( http://neilb.bitbucket.org/csvfix/manual/csvfix16/ExpressionLanguage.html ), что csvfix :

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

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

Вы можете временно удалить все цитированные новые строки, чтобы иметь возможность использовать обычные текстовые инструменты и повторно добавлять новые строки.

Например, если двойные кавычки:

 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 

Вы можете получить позицию из текста Perl :: 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 head -c 18 new.csv | wc -l , который говорит 2 (количество хороших строк). Таким образом, ошибка указана в строке 3 – и это действительно так, цитата вокруг r2c2 не закрыта.

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

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