Разделение CSV-файлов на многострочные ячейки

Тогда попробуйте исправить это, отредактировав файл /etc/pam.d/mdm. Он должен выглядеть следующим образом::

#%PAM-1.0
auth sufficient pam_rootok.so
#auth required pam_console.so
auth sufficient pam_permit.so
account sufficient pam_permit.so
session optional pam_keyinit.so force revoke

Это должно сработать.

3
08.03.2017, 02:13
4 ответа

Вы захотите разобрать CSV-файл, чтобы переиздать его более мелкими частями так, как вам нужно. Во время этой операции, возможно, вы даже захотите перевести его в другой, более строгий, четко определенный формат (например, о, я не знаю, json).

Ваш входной файл имеет довольно необычный формат. Модуль csv в Python, например, не может его разобрать, потому что в нем многосимвольный разделитель: , (пробел-запятая) вместо более распространенных ,. В противном случае вы сможете тривиально разобрать и повторно вывести файл с помощью 5 строк Python.

Вам придется найти другой работающий парсер или написать небольшой. Для начала попробуйте выяснить специфику формата, который у вас на руках, например, правила цитирования (например, что происходит, когда поле, процитированное с ", содержит ")

.
1
27.01.2020, 21:21

Вам, вероятно, придется разобрать его.Вот пример команды grep , объединенной в три команды sed , которые объединят многострочные строки в кавычках в одну строку (вы можете добавить конвейер к split -l ] в конце):

  grep -Eoz "((([^\",[:space:]]+|\"[!#-~[:space:]]+\"),? ?){4}[[:space:]]){1}" csvtest |  
  sed -e ':a' -e 'N' -e '$!ba' -e 's/\n\n/XXX new record XXX/g' |
  sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' |
  sed -e "s/XXX new record XXX/\n/g"  

Разбиение на части:

  • Параметр -E grep позволяет использовать расширенные регулярные выражения.
  • Параметр -o grep выводит только совпадающие элементы
  • Параметр -z grep обрабатывает символы новой строки как \ 0
  • {{1 }}
  • [^ \ ", [: space:]] + в шаблоне соответствует элементам без кавычек
  • \" [! # - ~ [: space:]] + \ " в шаблоне соответствует цитируемым элементам
  • , вам может потребоваться обновить шаблон цитируемые элементы для любых особых случаев, когда строки в кавычках содержат кавычки " или нестандартные диапазоны символов. Просто добавьте другие диапазоны символов после ~
  • Первый оператор sed заменяет две новые строки на XXX новая запись XXX . Вывод grep генерирует два символа новой строки между совпадениями.
  • Второй оператор sed заменяет каждую оставшуюся единственную новую строку пробелом.
  • Последний sed заменяет ранее добавленную XXX новую запись XXX обратно на одну новую строку

Вы можете добавить канал split -l в строку конец всему.

1
27.01.2020, 21:21

Для разбора CSV лучше всего использовать настоящий парсер CSV. В последних версиях модуля Perl Text::CSV вы можете указать многосимвольный разделитель полей

#!/usr/bin/env perl
use strict;
use warnings;
use Text::CSV;
use Data::Dump; # just for this demonstration

# the "binary" option allows newlines in field values
my $csv = Text::CSV->new({binary=>1, sep=>", "})
  or die Text::CSV->error_diag;

open my $fh, "<", "test.csv";

while (my $row = $csv->getline($fh)) {
    print "next row:\n";
    dd $row; # or do something more interesting
}

close $fh;
1
27.01.2020, 21:21

Я решил эту проблему, используя csvkit команды потоковой передачи для преобразования строк CSV в объекты JSON (, которые пропускают символы новой строки ),split-в преобразованном потоке JSON, а затем преобразовывают разделить файлы JSON обратно в CSV.

Gist с исполняемым скриптом находится здесь:https://gist.github.com/vergenzt/d717bbad096dcf4be2151c66af47bf3a

Общая структура:

FILE="..."
BASE="$(basename "$FILE" | cut -d. -f1)"

cat "$FILE" \
  | csvjson --stream --no-inference --snifflimit 0 \
  | gsplit -d --additional-suffix=.json -l $ROWS_PER_FILE -u - "${BASE}_"

for chunk_json in ${BASE}_*.json; do
  chunk_csv="$(basename "$chunk_json".json).csv"
  in2csv -f ndjson --no-inference "$chunk_json" > "$chunk_csv"
  rm "$chunk_json"
done

Согласно csvkit docs:

  • csvjsonиспользует потоковую передачу, если «--stream --no-inference --snifflimit 0установлено, а --skip-linesне установлено», и
  • in2csvиспользует потоковую передачу, если "--format ndjson --no-inferenceустановлено..."

Для масштабирования на моей машине (8 ГБ ОЗУ, процессор 1,8 ГГц )потребовалось около двух с половиной минут, чтобы разбить ~300-мегабайтный CSV-файл, содержащий ~4,5 млн строк, но только ~180 тыс. строк (новые строки без кавычек ).

0
12.02.2020, 20:40

Теги

Похожие вопросы