2011-12-12 13 views
5

ho la seguente stringa:Perl scissione e di espressione regolare

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

Sto cercando di dividerlo da /,/ ma solo se la sua non parentesi all'interno, per esempio, in questo caso il risultato dovrebbe essere :

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

grazie,

+1

Esiste una possibilità di parentesi nidificate? In tal caso, le espressioni rege potrebbero non essere adatte alla bolletta. –

+1

no, non è possibile. solo una coppia di parentesi, o coppia ma NON annidata – snoofkin

risposta

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

T la sua suddivisione su una virgola solo se la successiva parentesi successiva (se presente) non è una parentesi chiusa. Come annotato correttamente da Jack Maney, questo può portare al fallimento se possono verificarsi parentesi annidate.

Spiegazione:

,  # 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

In primo luogo è necessario decidere ciò che costituisce parentesi, e se possono essere nidificate. (per questa risposta, supporrò che possano esserlo). Poi è necessario rimuovere i blocchi paren dal testo e sostituirlo con un segnaposto:

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

Così ora si sono lasciati con qualcosa che assomiglia a:

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

ed è semplice ora di dividere su virgole. Quindi, su ciascuno dei pezzi divisi, cerca i token PAREN_\d+ e sostituiscili con quelli dell'array @parens. Potrebbe essere necessario utilizzare un nome segnaposto più esclusivo in base al contenuto sorgente.

Qualcosa di simile:

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

say for @segs; 

che per una stringa di esempio

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

stampe:

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

Non penso che sia necessario valutare '$ parens [$ 1]'. – TLP

0

Si potrebbe trovare più facile costruire un regexp per ciò che si vuole corrisponde, piuttosto che ciò che si desidera rimuovere. (Ciò presuppone che non si voglia limitare il numero di corrispondenze.)