2011-12-12 17 views
5

Mam następujący ciąg:Perl Split i wyrażenie regularne

'100% California Grown Olives, Water, Salt And Ferrous Gluconate (An,Iron, Derivative),asasd, sadasda' 

próbuję podzielić ją przez /,/ ale tylko wtedy, gdy jej nie nawiasach, na przykład, w tym przypadku wynik powinien być :

100% California Grown Olives 
Water 
Salt And Ferrous Gluconate (An,Iron, Derivative) 
asasd 
sadasda 

dzięki,

+1

Czy istnieje możliwość zagnieżdżania nawiasów? Jeśli tak, to regexes może nie pasować do rachunku. –

+1

nie, niemożliwe. tylko jedna para nawiasów lub para, ale NIE zagnieżdżona – snoofkin

Odpowiedz

11
@result = split(m/,(?![^()]*\))/, $subject); 

T dzieli go na przecinek tylko wtedy, gdy następny następujący nawias (jeśli jest) nie jest nawiasem zamykającym. Jak zauważył Jack Maney, może to prowadzić do niepowodzenia, jeśli mogą wystąpić zagnieżdżone nawiasy.

Objaśnienie:

,  # Match a comma. 
(?!  # Assert that it's impossible to match... 
[^()]* # any number of non-parenthesis characters 
\)  # followed by a closing parenthesis 
)  # End of lookahead assertion 
1

Najpierw trzeba zdecydować, co stanowi parens, a jeżeli mogą być zagnieżdżone. (dla tej odpowiedzi założę, że mogą być). Następnie trzeba usunąć te PAREN bloki z tekstem i wymienić go na zastępczy:

my @parens; 
$str =~ s/(\((?: (?0)|[^()])* \))/push @parens, $1; "PARENS_$#parens"/gex; 

Więc teraz pozostaje ci coś, co wygląda jak:

'100% California Grown Olives, Water, Salt And Ferrous Gluconate PAREN_0,asasd, 
sadasdas.' 

I to jest proste teraz podzielić to na przecinkach. Następnie na każdym z podzielonych kawałków, przeskanuj tokenów PAREN_\d+ i zamień je na te z tablicy @parens. Może być konieczne użycie bardziej unikalnej nazwy elementu zastępczego w zależności od zawartości źródłowej.

Coś jak:

s/PARENS_(\d+)/$parens[$1]/ge for my @segs = split /,\s*/ => $str; 

say for @segs; 

które na przykład wyrażenie:

my $str = "foo (b,a,r), baz (foo, (bar), baz), biz"; 

nadrukami:

foo (b,a,r) 
baz (foo, (bar), baz) 
biz 
+0

Nie sądzę, że musisz ocenić '$ parens [$ 1]'. – TLP

0

Może się okazać, że łatwiej zbudować regexp za to, co chcesz dopasować, a nie to, co chcesz usunąć. (Zakłada się, że nie chcesz ograniczać liczby dopasowań).