Как я могу regex ,, to, \ N, в моих CSV, чтобы mysqlimport понимал их? - PullRequest
1 голос
/ 27 октября 2011

Скажи, что у меня нормальный CSV, как

# helloworld.csv
hello,world,,,"please don't replace quoted stuff like ,,",,

Если я хочу, чтобы mysqlimport понял, что некоторые из этих полей NULL, тогда мне нужно:

# helloworld.mysql.csv
hello,world,\N,\N,"please don't replace quoted stuff like ,,",\N,\N

Я получил некоторую помощь от другого вопроса - Почему sed не заменяет перекрывающиеся шаблоны - но обратите внимание на проблему:

$ perl -pe 'while (s#,,#,\\N,#) {}' -pe 's/,$/,\\N/g' helloworld.csv
hello,world,\N,\N,"please don't replace quoted stuff like ,\N,",\N,\N
                                                           ^^

Как я могу написать регулярное выражение, чтобы оно не заменяло ,,, если они заключены в кавычки?

ФИНАЛЬНЫЙ ОТВЕТ

Вот последний использованный Perl, благодаря принятому ответу ниже:

perl -pe 's/^,/\\N,/; while (s/,(?=,)(?=(?:[^"]*"[^"]*")*[^"]*$)/,\\N/g) {}; s/,$/,\\N/' helloworld.csv

Это заботится о ведущих, конечных и не заключенных в кавычки пустых строках.

Ответы [ 2 ]

7 голосов
/ 27 октября 2011

Почему бы не использовать Text::CSV?Вы можете проанализировать файл с ним и затем использовать map для замены пустых полей на '\ N', например

use Text::CSV;

my $csv = Text::CSV->new({ binary => 1 }) or die Text::CSV->error_diag();
$csv->parse($line);           # parse a CSV string into fields
my @fields = $csv->fields();  # get the parsed fields

@fields = map { $_ eq "" ? '\N' : $_ } @fields;

$csv->combine(@fields);    # combine fields into a string
3 голосов
/ 27 октября 2011

Предполагая, что вы не избежали кавычек, вы можете убедиться, что вы заменили ,,, только если за ним следует четное количество кавычек:

$subject =~ 
    s/,       # Match ,
    (?=,)     # only if followed by another ,
    (?=       # and only if followed by...
     (?:      # the following group:
      [^"]*"  #  any number of non-quote characters, followed by one quote
      [^"]*"  #  the same thing again (even number!)
     )*       # any number of times, followed by
     [^"]*    # any number of non-quotes until...
     $        # end of string.
    )         # End of lookahead assertion
    /,\N/x
    g;

Введите:

foo,,bar,,,baz,"foo,,,oof",zap,,zip

Выход:

foo,\N,bar,\N,\N,baz,"foo,,,oof",zap,\N,zip
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...