Как избежать двойных кавычек внутри CSV? - PullRequest
0 голосов
/ 05 декабря 2018

В настоящее время у меня есть несколько CSV-файлов, где я не могу контролировать, как они создаются.Само собой разумеется ... они искажены и не соответствуют RFC 4180.

Пример ввода: Суть

",0000000000000000";"0";"1115S021121-12-1/2"M"
",0000000000000000";"0";"1115S021122-12-1/2"M"
",0000000000000000";"0";"1115S021123-12-1/2"M"
",0000000000000000";"0";"1115S021124-12-1/2"M"
"1";"1";"EXAMPLE_RANDOM" .    STRING"
"2,0000000000000000";"2";"this;can"also happen"

Желаемый результат:

",0000000000000000";"0";"1115S021121-12-1/2""M"

Я пытался это исправить, запустив sed с помощью регулярного выражения.Однако у меня есть только базовые знания о регулярных выражениях, и sed не хочет хорошо играть с моими попытками.

Может ли кто-нибудь помочь мне избежать дюймовой кавычки "внутри двойных кавычек? Я знаю, что подобные решения составляют всего 99%,я могу полагаться только на следующие факты.

  • Разделитель - это;
  • Вложение: "
  • " может встречаться несколько раз в указанном текстовом поле.

Это означает, что «или» может встречаться в указанных полях.Может ли кто-нибудь помочь мне заменить "с" "?

Моя попытка регулярного выражения объединить несколько сообщений stackoverflow.

 sed -E "s/[^\"](?<!;)\"(?!;|$)/\1"/g" $filename.test2   -> error
 sed "s/[^\"](?<!;)(\")(?!;|$)/\1/g" $filename.test2    -> error 
 ... about 10 more variations, some even without errors but no replaced strings.

Если у кого-то есть другое решение, отличное от regex, любая помощь очень ценится!

Редактировать: Благодаря @choroba Perl Wizzard. Следующий файл исправляет.

 cat $filename.test | perl -pe 's/(?<=[^;])"(?=[^;])/""/g' >  $filename.test2

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018
$ perl -MText::CSV_XS=csv -wE'csv(in=>csv(in=>"test.csv",sep=>";",allow_loose_quotes=>1,allow_loose_escapes=>1),always_quote=>1)'
",0000000000000000","0","1115S021121-12-1/2""M"
",0000000000000000","0","1115S021122-12-1/2""M"
",0000000000000000","0","1115S021123-12-1/2""M"
",0000000000000000","0","1115S021124-12-1/2""M"
"1","1","EXAMPLE_RANDOM"" .    STRING"
"2,0000000000000000","2","this;can""also happen"

Как заметил Чороба, с ";"в качестве выходного sep тоже:

$ perl -MText::CSV_XS=csv -wE'csv(in=>csv(in=>"test.csv",sep=>";",allow_loose_quotes=>1,allow_loose_escapes=>1),always_quote=>1,sep=>";")'
",0000000000000000";"0";"1115S021121-12-1/2""M"
",0000000000000000";"0";"1115S021122-12-1/2""M"
",0000000000000000";"0";"1115S021123-12-1/2""M"
",0000000000000000";"0";"1115S021124-12-1/2""M"
"1";"1";"EXAMPLE_RANDOM"" .    STRING"
"2,0000000000000000";"2";"this;can""also happen"

Объяснение добавлено по запросу:

Text :: CSV_XS - это модуль perl, который может анализировать и генерировать CSV очень гибким способом.Использование параметров / атрибутов для разрешения плохо отформатированного CSV.

  1. csv (in => "file.csv", ...) считывает файл во внутреннюю структуру

  2. sep => ";"устанавливает символ разделителя на ";"вместо значения по умолчанию ","

  3. allow_loose_quotes => 1 и allow_loose_escapes => 1 позволяют прочитать неправильный CSV и принять неэкранированные вложенные кавычки

  4. csv () возвращает ссылку на внутреннюю структуру, которая действительна для внешнего вызова csv, который генерирует выходной файл csv (in => csv (in => "file.csv")

  5. Последние два аргумента устанавливают для sep также значение ";" и выводят все поля в кавычки, поскольку требуется OP

См. https://metacpan.org/module/Text::CSV_XSдля всех опций и примеров

Отформатированный в скрипте, он может выглядеть как

use Text::CSV_XS qw( csv );

csv (                    # Outer function
    always_quote => 1,   # Quote all field
    sep          => ";", # Use ; instead of ,
    in           =>      # Input
        csv (            #   comes from inner function
            in                  => "test.csv", # a file
            sep                 => ";",        # ; instead of ,
            allow_loose_quotes  => 1,          # allow ,"foo"bar",
            allow_loose_escapes => 1,          # idem
            )
    );
0 голосов
/ 05 декабря 2018

Проверочные утверждения Perl к результату!

perl -pe 's/(?<=[^;])"(?=[^;\n])/""/g' 

Т.е. если есть ", которому не предшествует ; и за которым не следует ;, замените его на "".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...