LINUX.ORG.RU

Perl, split

 ,


0

1

Нужно широкий (170 колонок) csv-файл разделить на поля и записать в базу, при этом все колонки должны прочитаться. Ерунда получается при разделении через split. Решил сделать вручную, так как через Text::CSV_XS еще больше проблем.

#!/usr/bin/perl
use strict;
use Data::Dumper;

my $str = 'a;b;;d;e;;;;';
my @col = split (/;/, $str);

print $str,"\n";
print Dumper @col,"\n";


a;b;;d;e;;;;
$VAR1 = 'a';
$VAR2 = 'b';
$VAR3 = '';
$VAR4 = 'd';
$VAR5 = 'e';
$VAR6 = '
';

★★

Последнее исправление: WinLin2 (всего исправлений: 2)

Ответ на: комментарий от WinLin2

слушай, когда я писал подобное на 1С, я читал построчно, а потом для каждой строки заменял символ-разделитель на перевод строки и опять читал построчно. так точно работало.

bvn13 ★★★★★
()
Ответ на: комментарий от bvn13
#!/usr/bin/perl

use strict;
use utf8;
use Data::Dumper;

my $str = 'a1;b2;;d4;e5;;;;';
$str =~ s/;/ ;/g;

my @col = map { substr ($_, 0, -1) }  split( /;/, $str);

print $str,"\n";
print Dumper @col,"\n";
a1 ;b2 ; ;d4 ;e5 ; ; ; ;
$VAR1 = 'a1';
$VAR2 = 'b2';
$VAR3 = '';
$VAR4 = 'd4';
$VAR5 = 'e5';
$VAR6 = '';
$VAR7 = '';
$VAR8 = '';
$VAR9 = '
';



Добавил в каждую колонку пробел, потом его удалил.

WinLin2 ★★
() автор топика

perldoc -f split:

If LIMIT is omitted (or, equivalently, zero), then it is usually treated as if it were instead negative but with the exception that trailing empty fields are stripped (empty leading fields are always preserved); if all fields are empty, then all fields are considered to be trailing (and are thus stripped in this case). Thus, the following:

           print join(':', split(/,/, 'a,b,c,,,')), "\n";

produces the output «a:b:c», but the following:

           print join(':', split(/,/, 'a,b,c,,,', -1)), "\n";

produces the output «a:b:c:::».

anonymous
()

Text::CSV

В чём у вас с ним проблема? Учтите что то что вы разделяете split’ом — не соответствует стандарту CSV https://tools.ietf.org/html/rfc4180

anonymous
()
Ответ на: комментарий от anonymous

Спасибо, удалил велосипед.

Не нашел в Text::CSV, как разделить строку файла по полям
и одновременно хранить в ее первоначальном виде.

WinLin2 ★★
() автор топика

Сложности-то какие, и не лень вам?

>>> 'a;b;;d;e;;;;'.split(';')
['a', 'b', '', 'd', 'e', '', '', '', '']
>>> import re
>>> re.split(';', 'a;b;;d;e;;;;')
['a', 'b', '', 'd', 'e', '', '', '', '']
>>> import csv
>>> next(csv.reader(['a;b;;d;e;;;;'], delimiter=';'))
['a', 'b', '', 'd', 'e', '', '', '', '']
slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от Olegymous
my @cols = @{$csv->getline ($fh)};
$csv->column_names (@cols);
while (my $row = $csv->getline_hr ($fh)) {
    print $row->{price};
}


В таком варианте можно увидеть строку до разбиения на поля?

WinLin2 ★★
() автор топика
Последнее исправление: WinLin2 (всего исправлений: 1)

Неужели на CPAN нет подходящего модуля? Одно из правил инженера: вместо изобретения велосипеда поищи готовое решение, скорее всего оно будет работать лучше.

dvetutnev
()
Ответ на: комментарий от WinLin2

Почему split пропускает повторяющиеся пустые поля ‘;;;;’?

Первый параметр split - regex. Он по умолчанию жадный(greedy).

https://www.ultraedit.com/support/tutorials-power-tips/ultraedit/non-greedy-perl-regex.html

TL;DR Our non-greedy ? operator tells the Perl regular expression engine to match as little data as possible

imatveev13
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.