Newsgroup: it.comp.lang.perl
Titolo: "Semplice" RE?

Avrei un problema che mi sembrava semplicissimo, fino a quando non ho
tentato di risolverlo:
Avrei una stringa tipo questa:
$string = << '__EOS__';
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
__EOS__
vorrei sostituire le "{a}" e le "{a}.*?{/a}" con una Z, in modo che il
risultato dell'operazione trasformi la string così:
"000 Z 111 {b} 222 Z 333
000 Z 111 {b} 222 Z 333
000 Z 111 {b} 222 Z 333"
La string contiene numeri ripetuti solo per chiarezza dell'esempio, in
realtà potrà contenere tutti i caratteri possibili (.+) e le righe non
saranno per nulla organizzate così regolarmente come nell'esempio, e neppure
le "{a}" e le "{/a}" avranno ricorrenza regolare.
Qualcuno ha qualche idea "veloce"?
Grazie
--
-.. --- -- .. --.. .. ---
-.. . -- .. -.-. .... . .-.. .. ...

Qualcuno ha qualche idea "veloce"?
"Tutti i caratteri possibili" sono proprio "tutti"? Se ne puoi escludere
qualcuno (per esempio, una tabulazione), e per una certa interpretazione
del problema, un'idea veloce, che non costringe a fare un'analisi lessicale
completa, potrebbe essere:
  $string =~ s/{a}/\t/g;
  $string =~ s|\t[^\t]+?{/a}|Z|g;
  $string =~ s/\t/Z/g;
Ciao.

   000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333 {/a}
hmmm... esattamente, molto interessante...
Nel frattempo qualcuno mi ha suggerito che esiste una FAQ che io non avevo
trovato e che tratta appunto del problema :-S;
perldoc -q nesting
Grazie mille per l'interesse.


 Qualcuno ha qualche idea "veloce"?
Boh. Guarda se ti piace questa. 
 
 $string =~ s/
  {a}
    (  
       ( ( [^{] | { (?!\/a}) )*? (?=({a}|$)) )
        |
       (.*?{\/a})
     )
	/Z$2/xg;
L'idea di Giovanni è sicuramente migliore, però (salvo che invece del \t
userei \0).
Max.

 wrote in message
news:84s7qu43sat37igar...@4ax.com...


 wrote in message
news:Pine.LNX.4.21.02100...@localhost.localdomain...


 risolvere. Resta il problema dei blocchi nested {a}...{a}...{/a}...{/a}.
Se hai blocchi annidati non puoi farlo con una singola applicazione di una
regexp. Una cosa del genere dovrebbe funzionare:
 1 while(  $string =~ s/{a}([^{]|{(?!a}))*?{\/a}/Z/g );
 $string =~ s/{a}/Z/g;
Max

Per quelli che hanno seguito il thread.
Ho poi usato questa implementazione:
=========== CODE ============
my $string = << '__EOS__';
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
000 {a} 111 {b} 222 {a} XXX {b} XXX {/a} 333
__EOS__
my $START = qr/\{a\}/;
my $END = qr/\{\/a\}/;
$string =~ s/
                   $START
                   (?:
                     (
                       (?: (?! $START) (?! $END ) . )*
                     )
                     $END
                   )?
                 /Z/xsg ;
print $string;
========== END CODE ===========
La linea (?: (?! $START) (?! $END ) . )* che è la chiave del sistema, è
stata ispirata da perldoc -q nesting.
La RE completa non risolve il caso di {a}...{a}...{/a}...{/a}, ma va bene
così, perché per l'applicazione in cui è usata, questa eventualità sarebbe
un non sense.
(esempio: un link HTML nidificato <a href...><a href...>...</a></a> non
avrebbe senso)
Grazie a quanti hanno aiutato.
