Как разбить строку на массив запятыми, но игнорировать запятые внутри двойных кавычек?

У меня есть строка:

$string = 'Paul,12,"soccer,baseball,hockey",white';

Я пытаюсь разбить это на @array, у которого есть 4 значения, поэтому

print $array[2];

Дает

soccer,baseball,hockey

Как это сделать? Помогите!

Ответ 1

В ответ на то, как это сделать с помощью Text:: CSV (_PP). Вот быстрый.

#!/usr/bin/perl

use strict;
use warnings;

use Text::CSV_PP;
my $parser = Text::CSV_PP->new();

my $string = "Paul,12,\"soccer,baseball,hockey\",white";

$parser->parse($string);
my @fields = $parser->fields();

print "$_\n" for @fields;

Обычно можно установить Text::CSV или Text::CSV_PP через утилиту cpan.

Чтобы обойти невозможность установки модулей, я предлагаю вам использовать реализацию "чистого Perl", чтобы вы могли "установить" ее. Вышеприведенный пример будет работать при условии, что вы скопировали текст Text::CSV_PP источника в файл с именем CSV_PP.pm в папке с именем Text created в том же каталоге, что и ваш script. Вы также можете поместить его в другое место и использовать метод use lib 'directory', как обсуждалось ранее. См. здесь и здесь, чтобы увидеть другие способы обойти ограничение установки с помощью модулей CPAN.

Ответ 2

Просто используйте Текст:: CSV. Как вы можете видеть из источника, получение правильного синтаксического анализа CSV довольно сложно:

sub _make_regexp_split_column {
    my ($esc, $quot, $sep) = @_;

    if ( $quot eq '' ) {
        return qr/([^\Q$sep\E]*)\Q$sep\E/s;
    }

   qr/(
        \Q$quot\E
            [^\Q$quot$esc\E]*(?:\Q$esc\E[\Q$quot$esc\E0][^\Q$quot$esc\E]*)*
        \Q$quot\E
        | # or
        [^\Q$sep\E]*
       )
       \Q$sep\E
    /xs;
}

Ответ 3

Стандартный модуль Text:: ParseWords также сделает это.

my @array = parse_line(q{,}, 0, $string);

Ответ 4

Используйте это регулярное выражение: m/( "[^" ] + "| [^,] +) (?:,\s *)?/g;

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

Вот пример кода и соответствующий вывод.

my $string = "Word1, Word2, \"Commas, inbetween\", Word3, \"Word4Quoted\", \"Again, commas, inbetween\"";
my @arglist = $string =~ m/("[^"]+"|[^,]+)(?:,\s*)?/g;
map { print $_ , "\n"} @arglist;

Вот результат:

Word1
Word2
"Commas, inbetween"
Word3
"Word4Quoted"
"Again, commas, inbetween"

Ответ 5

попробуйте это

  @array=($string =~ /^([^,]*)[,]([^,]*)[,]["]([^"]*)["][,]([^']*)$/);

массив будет содержать ожидаемый вами результат.

Ответ 6

use strict;
use warning;
#use Data::Dumper;

my $string = qq/Paul,12,"soccer,baseball,hockey",white/;

#split string into three parts
my ($st1, $st2, $st3) = split(/,"|",/, $string);
#output: st1:Paul,12 st2:soccer,baseball,hockey  st3:white  

#split $st1 into two parts
my ($st4, $st5) = split(/,/,$st1);

#push records into array
push (my @test,$st4, $st5,$st2, $st3 ) ;

#print Dumper \@test;
print "$test[2]\n";

выход:

soccer,baseball,hockey 

#$VAR1 = [
#          'Paul',
#         '12',
#          'soccer,baseball,hockey',
#          'white'
#        ];

Ответ 7

$string = "Пол, 12, \" футбол, бейсбол, хоккей \ ", белый";

1 while ($ string = ~ s # "(.?), (.?)" #\ "$ 1aaa $2 \" # g);

@array = map {$ _ = ~ s/aaa//g; $_ = ~ s/\ "//g; $_} split (/,/, $string);

$ "=" \n ";

print "$ array [2]";