POD2-IT

 view release on metacpan or  search on metacpan

IT/perlfaq6.pod  view on Meta::CPAN

    s{ <                 # parentesi angolare aperta
        (?:              # raggruppamento senza la creazione di riferimento
                         #   all'indietro
             [^>'"] *    # 0 o piu` cose che non sono un >, ne' un ' ne' un "
                |        #    o altrimenti
             ".*?"       # una sezione tra doppi apici (match non-greedy)
                |        #    o altrimenti
             '.*?'       # una sezione tra apici singoli (match non-greedy)
        ) +              #   il tutto una o piu` volte
       >                 # parentesi angolare chiusa
    }{}gsx;              # sostituisci con nulla, cioe` cancella

Non E<egrave> chiaro come un brano di prosa, ma E<egrave> molto utile per
descrivere il significato di ciascuna parte del pattern.

=item Delimitatori differenti

BenchE<eacute> normalmente pensiamo a pattern delimitati da caratteri C</>,
essi possono essere delimitati da quasi qualunque carattere.
perlre descrive questo aspetto. Ad esempio, l'istruzione C<s///> usata
sopra usa le parentesi come delimitatori. Scegliere un altro
delimitatore puE<ograve> evitare la necessitE<agrave> di marcare il carattere
affinchE<eacute> sia interpretato letteralmente:

    s/\/usr\/local/\/usr\/share/g;    # cattiva scelta del delimitatore
    s#/usr/local#/usr/share#g;        # scelta migliore

=back

=head2 Sto avendo dei problemi nel fare il match su piE<ugrave> di una linea. Cosa c'E<egrave> di sbagliato?
X<regex, multilinea> X<regexp, multilinea> X<espressione regolare, multilinea>

O non avete piE<ugrave> di una linea nella stringa che state prendendo in
considerazione (verosimilmente), oppure non state usando il modificatore/i
corretto nel vostro pattern (forse).

Ci sono molti modi per ottenere dei dati con piE<ugrave> linee in una
stringa. Se volete che ciE<ograve> avvenga automaticamente mentre leggete
l'input, vorrete impostare $/ (verosimilmente a '' per i paragrafi oppure
ad C<undef> per l'intero file) per darvi la possibilitaE<agrave> di leggere
piE<ugrave> di una riga alla volta.

Leggete L<perlre>: vi aiuterE<agrave> a decidere quale tra C</s> e C</m>
(oppure entrambi) potreste voler usare: C</s> permette al punto di includere i
ritorni a capo e C</m> permette al segno d'omissione (C<^>, NdT) ed al simbolo
del dollaro di effettuare il match in prossimitE<agrave> di un
ritorno a capo, non solo alla fine della stringa. Dovete tuttavia
assicurarvi di avere veramente una stringa con piE<ugrave> linee.

Per esempio, questo programma individua le parole duplicate, anche se esse
sono ripartite tra le interruzioni di linea (ma non se lo sono tra le
interruzioni dei paragrafi). Per questo esempio non ci serve C</s>,
perchE<eacute> non stiamo usando il punto in un'espressione regolare
che vogliamo attraversi i confini di linea. Non ci serve neppure C</m>
perchE<eacute> non vogliamo che il segno d'omissione o il simbolo del
dollaro effettuino il match in un qualsiasi punto all'interno del
record vicino ai ritorni a capo. Ma E<egrave> imperativo che $/ sia
impostato a qualcosa di diverso rispetto al valore predefinito, altrimenti
non riusciremo mai a leggere un record composto da piE<ugrave> linee.

    $/ = '';  		# memorizza piu` dell'intero paragrafo, non solo una linea
    while ( <> ) {
	while ( /\b([\w'-]+)(\s+\1)+\b/gi ) {  	# la parola inizia con un carattere alfanumerico
	    print "$1 e` un duplicato, al paragrafo $.\n";
	}
   }

Qui c'E<egrave> il codice che trova le frasi che iniziano con "From " ["da", NdT]
(che dovrebbe essere storpiato da molti programmi di posta):

    $/ = '';  		# memorizza piu` dell'intero paragrafo, non solo una linea
    while ( <> ) {
	while ( /^From /gm ) { # /m fa si` che ^ effettui un match vicino a \n
	    print "primo from nel paragrafo $.\n";
	}
    }

Qui c'E<egrave> il codice che trova ogni cosa tra START [inizio, NdT] ed
END [fine, NdT] nel paragrafo:

    undef $/;  		# memorizza l'intero file, non solo una linea od un paragrafo
    while ( <> ) {
	while ( /START(.*?)END/sgm ) { # /s fa si` che il . attraversi i confini di linea
	    print "$1\n";
	}
    }

=head2 Come posso tirar fuori le linee tra due pattern che sono loro stessi su linee diverse?
X<..>

Potete usare l'esotico operatore C<..> (documentato in L<perlop>):

    perl -ne 'print if /INIZIO/ .. /FINE/' file1 file2 ...

Se volevate il testo e non le linee, avreste dovuto usare:

    perl -0777 -ne 'print "$1\n" while /INIZIO(.*?)FINE/gs' file1 file2 ...

Ma se volete occorrenze innestate [inglese "nested", NdT] di
C<INIZIO> e C<FINE>, vi scontrerete con il problema descritto nella
domanda contenuta in questa sezione a proposito della ricerca di
corrispondenze di testo bilanciato.

Ecco un altro esempio d'uso di C<..>:

    while (<>) {
        $nell_header =   1  .. /^$/;
        $nel_corpo   = /^$/ .. eof();
    # ora scegliete
    } continue {
        reset if eof();    # mette a posto $.
    }

=head2 Ho messo un'espressione regolare in $/ ma non ha funzionato. Cosa c'E<egrave> di sbagliato?
X<$/, regex in> X<$INPUT_RECORD_SEPARATOR, regex in>
X<$RS, regex in>

Fino a Perl 5.8.0, $/ deve essere una stringa. Questo potrebbe cambiare nel
5.10, ma non ci sperate. Fino ad allora, potete usare questi esempi se davvero
ne avete bisogno.

Se avete File::Stream, questo E<egrave> semplice.

	 use File::Stream;
         my $stream = File::Stream->new(
                  $filehandle,
                  separator => qr/\s*,\s*/,
         );

	 print "$_\n" while <$stream>;

IT/perlfaq6.pod  view on Meta::CPAN

che E<egrave> contenuto in \W con aggiunte le cifre e l'underscore,
o C</[\W\d_]/>.

=head2 Come si puE<ograve> fare il quote di una variabile da usare in una regex?
X<regex, escaping> X<regexp, escaping> X<espressione regolare, escaping>

Il parser del Perl espanderE<agrave> i riferimenti a $variabile e @variabile
in espressioni regolari a meno che il delimitatore sia un singolo quote [un
apice, NdT]. Ricordate inoltre che il lato destro di una sostituzione
C<s///> viene considerato come una stringa doppiamente quotata (delimitata
da virgolette, NdT) (si veda L<perlop> per maggiori dettagli). Ricordate
anche che ogni carattere speciale delle regex avrE<agrave> affetto, a meno
che non si preceda la sostituzione con \Q. Di seguito un esempio:

    $stringa = "Placido P. Octopus";
    $regex  = "P.";

    $stringa =~ s/$regex/Polyp/;
    # $stringa e` ora "Polypacido P. Octopus"

Siccome C<.> E<egrave> un carattere speciale per quanto riguarda le
espressioni regolari, e puE<ograve> trovare qualsiasi carattere, la
regex C<P.> qui ha trovato il <Pl> contenuto nella stringa originale.

Per effettuare l'escaping del significato speciale di C<.>, utilizziamo
C<\Q>:

    $stringa = "Placido P. Octopus";
    $regex  = "P.";

    $stringa =~ s/\Q$regex/Polyp/;
    # $string e` ora "Placido Polyp Octopus"

L'utilizzo di C<\Q> fa si che il <.> contenuto nell'espressione regolare
sia trattato come un carattere regolare, cosicchE<eacute> C<P.> possa
trovare una C<P> seguita da un punto.

=head2 A cosa serve realmente C</o>?
X</o>

L'uso di una variabile in un match di un'espressione regolare forza una
rivalutazione (e probabilmente ricompilazione) ogni qualvolta ci si imbatte
nell'espressione regolare. Il modificatore C</o> vincola la regex la prima
volta che viene usata. Questo avviene sempre in una espressione regolare
costante, ed infatti il pattern viene compilato nel formato interno al
momento della compilazione dell'intero programma.

L'uso di C</o> E<egrave> irrilevante a meno che l'interpolazione di variabili
non venga utilizzata nel pattern e, se E<egrave> cosE<igrave>, il motore
delle regex non saprE<agrave> nE<eacute> si interesserE<agrave> di eventuali
variazione delle variabili dopo la I<primissima> valutazione del pattern.

C</o> viene usato spesso per ottenere un ulteriore grado di efficienza,
non eseguendo le valutazioni successive quando sapete che la cosa non
avrE<agrave> importanza (perchE<eacute> sapete che le variabili
non cambieranno), oppure, piE<ugrave> di rado, quando non volete che
la regex si accorga se le variabili cambiano.

Per esempio, ecco un programma "paragrep":

    $/ = '';  # modalita` paragrafo
    $pat = shift;
    while (<>) {
        print if /$pat/o;
    }

=head2 Come faccio ad usare un'espressione regolare per togliere da un file i commenti in stile C?

BenchE<eacute> ciE<ograve> possa effettivamente essere realizzato, E<egrave>
molto piE<ugrave> difficile di quanto potreste pensare. Per esempio, questo
programma di una sola riga

    perl -0777 -pe 's{/\*.*?\*/}{}gs' pippo.c

funzionerE<agrave> in molti casi, ma non in tutti. Vedete, E<egrave> troppo
ingenuo per certi tipi di programmi C, in particolare quelli che 
contengono ciE<ograve> che sembrano essere commenti all'interno di stringhe
incluse tra virgolette. Per questo, avreste bisogno di qualcosa come questo,
creato da Jeffrey Friedl ed in seguito modificato da Fred Curtis.

    $/ = undef;
    $_ = <>;
    s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse;
    print;

Questo, naturalmente, potrebbe essere piE<ugrave> leggibile con il
modificatore C</x>, aggiungendovi spazi e commenti. Eccolo espanso, per
cortese concessione di Fred Curtis.

    s{
       /\*         ##  Inizio di un commento /* ... */
       [^*]*\*+    ##  Non-* seguito da 1-o-piu` *
       (
         [^/*][^*]*\*+
       )*          ##  0-o-piu` cose che non iniziano con /
                   ##    ma terminano con '*'
       /           ##  Fine di un commento of /* ... */
     |         ##     OPPURE  diverse cose che non sono commenti:
       (
         "           ##  Inizio di una stringa " ... "
         (
           \\.           ##  Carattere preceduto da \
         |               ##    OPPURE
           [^"\\]        ##  Non "\
         )*
         "           ##  Fine di una stringa " ... "
       |         ##     OPPURE
         '           ##  Inizio di una stringa ' ... '
         (
           \\.           ##  Carattere preceduto da \
         |               ##    OPPURE
           [^'\\]        ##  Non '\
         )*
         '           ##  Fine di una stringa ' ... '
       |         ##     OPPURE
         .           ##  Qualsiasi altro carattere
         [^/"'\\]*   ##  Caratteri che non sono l'inizio di un commento, non cominciano una stringa, non sono il carattere \
       )
     }{defined $2 ? $2 : ""}gxse;

Una piccola modifica rimuove anche i commenti C++:



( run in 1.626 second using v1.01-cache-2.11-cpan-54e63673c56 )