2012-02-24 1 views
8

私はカンマで区切られた値を含むいくつかのフィールドを持つデータベースを持っています。私はこれらのフィールドをPerlで分割する必要があります。ただし、分割したくない括弧で囲まれたネストされたCSVが値の一部に続くことを除けば、簡単です。角かっこ内の場合を除き、コンマで区切られたPerlの分割リスト?

例:

recycling, environmental science, interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics), consumer education 

の分割 "" 私に与える:

recycling 
environmental science 
interdisciplinary (e.g. 
consumerism 
waste management 
chemistry 
toxicology 
government policy 
and ethics) 
consumer education 

私が欲しいものです:

recycling 
environmental science 
interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics) 
consumer education 

任意のPerlの正規表現(perts)が手を貸すことができます?

私は結果を返しません似たSO postで見つかった正規表現の文字列を変更しようとしている:

#!/usr/bin/perl 

use strict; 
use warnings; 

my $s = q{recycling, environmental science, interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics), consumer education}; 

my @parts = $s =~ m{\A(\w+) ([0-9]) (\([^\(]+\)) (\w+) ([0-9]) ([0-9]{2})}; 

use Data::Dumper; 
print Dumper \@parts; 
+0

これまでに何を試しましたか?あなた自身で最初に努力してから、あなたがしたことを示す質問をしてください。 –

+0

正規表現を使用してネストされた式を解析することはできません。本格的なパーサが必要です。 – Ether

+0

[Text :: CSV](http://search.cpan.org/perldoc?Text::CSV)を見て、必要なことをするためにそれを微調整できるかどうかを見てください。 – TLP

答えて

9

はこれを試してみてください:

my $s = q{recycling, environmental science, interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics), consumer education}; 

my @parts = split /(?![^(]+\)), /, $s; 
+0

私はちょうど同じこと[ここ](http://stackoverflow.com/questions/8481345/perl-split-and-regular-expression)が見つかりました。ありがとう! – calyeung

0

は、誰もがあなたがいずれかでそれをしなければならないと言ったのステップ? ループ内の値をスライスすることができます。あなたの例を考えれば、このようなものを使うことができます。

use strict; 
use warnings; 
use 5.010; 

my $s = q{recycling, environmental science, interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics), consumer education}; 

my @parts; 
while(1){ 

     my ($elem, $rest) = $s =~ m/^((?:\w|\s)+)(?:,\s*([^\(]*.*))?$/; 
     if (not $elem) { 
       say "second approach"; 
       ($elem, $rest) = $s =~ m/^(?:((?:\w|\s)+\s*\([^\)]+\)),\s*(.*))$/; 
     } 
     $s = $rest; 
     push @parts, $elem; 
     last if not $s; 

} 

use Data::Dumper; 
print Dumper \@parts; 
2

選択したソリューションは優れているが、それ以外は言う方には、正規表現は、ネストされた括弧にマッチします再帰要素を持っています。以下はうまく機能する

use strict; 
use warnings; 

my $s = q{recycling, environmental science, interdisciplinary (e.g., consumerism, waste management, chemistry, toxicology, government policy, and ethics), consumer education}; 

my @parts; 

push @parts, $1 while $s =~/
((?: 
    [^(),]+ | 
    (\(
    (?: [^()]+ | (?2))* 
    \)) 
)*) 
(?: ,\s* | $) 
/xg; 


print "$_\n" for @parts; 

括弧がさらにネストされていても、いいえ、それはきれいではありませんが、動作します!

+0

+1(平衡)溶液の場合。 :) – zx81

0

ループとsplitを使用する別のアプローチです。私はパフォーマンスをテストしていませんが、これは先読みの正規表現のソリューションより速いはずです($strの長さが増える)?

my @elems = split ",", $str; 
my @answer; 
my @parens; 
while(scalar @elems) { 
    push @answer,(shift @elems) while($elems[0] !~ /\(/); 
    push @parens, (shift @elems) while($elems[0] !~ /\)/); 
    push @answer, join ",", (@parens, shift @elems); 
    @parens =(); 
} 
関連する問題