У меня есть 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 не закрыта.