Pagina 1 di 6 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 54
  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2003
    Messaggi
    34

    PILLOLINA sulle espresioni regolari (1/2)

    Frequento da poco il forum e notare un paio di post di help sulle espressioni regolari mi ha spinto a scrivere questa pillolinainaina (ci vorrebbe un intero libro) su tale argomento ed in modo specifico sulle 'espressioni regolari perl compatibili'. So che questo è + un argomento di perl che di PHP, ma io conosco poco e niente il perl e le espressoni regolari le ho apprezzate in accoppiata al PHP quindi prego i moderatori di non spostare il post!

    Mi scuso con tutti se quanto scrivo non è di semplice lettura ma le espressioni regolari non sono noccioline.

    (In questo testo il termine ‘preg’ indica l’espressione regolare, il termine ‘stringa’ indica la sequenza di caratteri su cui stiamo applicando l’espressione regolare cioè la stringa sulla quale cerchiamo o vogliamo sostituire qualcosa)

    CONCETTI GENERALI
    - 1 –
    Le preg sono frutto di una mente diabolica e contorta, sono un insieme di caratteri incomprensibili che vengono usate dai matti per fare ricerche o sostituzioni in una stringa ma, una volta imparate, il demone diventa santo e di raddrizza!!!

    - 2 –
    Le preg cominciano e terminano con un delimitatore, il più usato è lo slash '/' ma può essere usato qualsiasi altro carattere alfanumerico ad eccezione dello spazio e assimilati (vedere funzione isspace()), consiglio comunque di cambiare delimitatore soltanto se lo slash viene usato all’interno della preg in modo intenso; per farla breve il primo carattere della preg viene assunto come delimitatore e il parser deve trovarne uno identico alla fine, a questa regola fanno eccezioni le parentesi tonda ‘(‘ , quadra ‘[‘ o graffa ’{‘ che sia, in questo caso il delimitatore finale deve essere la parentesi inversa ‘)’,’]’,’}’;

    - 2 –
    Nella preg, dopo il delimitatore finale ci vanno (opzionali) i modificatori, in pratica dei caratteri che modificano il criterio di ricerca; una preg senza modificatori ha ovviamente una impostazione di default: è binary safe (cioè distingue le maiuscole dalle minuscole) e agisce su una singola riga cioè se la stringa contiene un a capo ‘\n’ questo è considerato come fine della stringa

    - 4 –
    Nelle preg alcuni caratteri hanno un significato speciale per da qui il nome di metacaratteri, per far perdere il significato speciale al metacarattere bisogna anteporgli uno backslash ‘\’, mi spiego ‘$’ è un metacarattere che indica la fina della stringa ‘\$’ è un semplicissimo dollaro, ovviamente anche lo backslash è un meta carattere per cui una stringa “cane\gatto” la devo scrivere come “cane\\gatto” !

    5) Le preg tra doppi apici (“) devono fare i conti con il PHP; supponiamo di voler trovare la seguente sequenza di caratteri “$nome \ $cognome” la preg che devo passare all’angine è “/\$nome \\ \$cognome/” ma anche per il PHP i caratteri slash ‘\’ e dollaro ‘$’ hanno un significato speciale per cui nello script dovrò scrive:
    $preg=”/\\\$nome \\\\ \\\$cognome/” oppure $
    preg=’/\$nome \\ \$cognome/’

    COME RAGIONA L’ENGINE PREG
    Queste sono le + importanti regole che l’engine segue nel valutare una preg e nell’effetuare la ricerca o una sostituzione in una stringa. Tali regole hanno un importanza fondamentale, saperle ci fa capire come lavora l’engine e quindi come scrivere al meglio le preg

    Regola 1
    L’engine valuta una preg da sinistra a destra e genera una serie di ‘azioni di confronto’ che verranno applicate alla stringa secondo la regola (2) la preg è riscontrata integralmente in una stringa solo se tutte le azioni di confronto hanno esito positivo nello stesso ordine in cui appaiono nella preg (ricordate sempre da sinistra a destra)

    Regola 2
    L’engine scorre la stringa partendo da sinistra e verifica se la preg è soddisfatta integralmente, in caso negativo passa alla posizione successiva (a destra) verificando nuovamente la preg, il ciclo si ripete sino a quando la preg non viene riscontrata oppure si raggiunge la fine della stringa. La prima posizione assunta dall’engine è prima del primo carattere della stringa, la seconda posizione è tra il primo e il secondo carattere, la terza tra il secondo e il terzo carattere e così via sino all’ultima posizione che si trova dopo l’ultimo carattere della stringa; Faccio un esempio: supponiamo di avere una stringa “abc” questa è la sequenza delle posizioni (indicate con un punto ‘.’) assunte dall’engine: “.abc” “a.bc” “ab.c” “abc.” (il puntatore si sposta tra i caratteri).

    Regola 3
    La preg può contenere atomi e asserzioni. Gli atomi hanno un peso in caratteri, le asserzioni no! Un atomo è un carattere che deve essere riscontrato (cioè deve essere presente) in un preciso punto della stringa, le asserzioni indicano semplicemente il verificarsi di una determinata condizione in quel determinato punto.

    Il carattere punto ‘.’ in una preg è un metacarattere, è un atomo ed indica qualsiasi carattere:
    “/a./” trova riscontro in “aa”,”ab”,”ac”, ...

    Queste alcune asserzioni:
    ^ inizio stringa o di riga (dipende dal modificatore)
    $ fine stringa o di riga (dipende dal modificatore)
    \b confine di parola
    (?=xxx) posizione in cui l’espressione xxx viene riscontrata
    (?!xxx) posizione in cui l’espressione xxx non viene riscontrata

    Cerchiamo di chiarire le idee con qualche esempio:
    Abbiamo una stringa: “abacad”,
    chiediamo all’engine di fare una ricerca su tutta la stringa, cioè di non fermarsi appena la nostra preg risulta verificata ma di continuare sino alla fine ed eventualmente restituire risultati multipli (questa è la differenza tra le funzioni preg_match() e preg_match_all() ).
    Analizziamo i risultati di queste preg:
    “/ab/”:
    come risultato avremo “ab” (un solo riscontro) perché ho chiesto all’engine di trovare i due atomi ‘a’ e ‘b’ in successione, ogni atomo ha peso 1 per cui tutta la preg ha peso 2 e quindi se riscontrata restituisce 2 caratteri.
    “/a./:
    come risultato avremo “ab”,”ac”,”ad” (3 riscontri) perché ho chiesto all’engine di trovare i due atomi ‘a’ e ‘.’(qualsiasi carattere), in successione, ogni atomo ha peso uno per cui anche in questo caso tutta la preg ha peso 2 e quindi ad ogni riscontro restituisce 2 caratteri.
    “/a(?=b)/”:
    come risultato avremo “a” (un solo riscontro) perché ho chiesto all’engine di trovare l’atomo ‘a’ seguito dall’asserzione ‘b’, l’atomo ha peso 1 l’asserzione ha peso 0, quindi facendo le somme dei pesi la preg ha peso totale 1 e quindi se riscontrata restituisce 1 carattere.
    “/a(?=.)/:
    come risultato avremo “a”,”a”,”a” (3 riscontri) perché ho chiesto all’engine di trovare l’atomo ‘a’ seguito dall’asserzione ‘.’ (qualsiasi carattere), l’atomo ha peso 1 l’asserzione ha peso 0, quindi facendo le somme dei pesi la preg ha peso totale 1 e quindi ad ogni riscontro restituisce 1 carattere.

    Questo un esempio pratico e spero esplicativo:
    Codice PHP:
    $str="GialloVerdeBiancoGialloRossoGialloVerdeGialloBlu" ;
    $replace1=preg_replace("/Giallo(?=Verde)/","Nero",$str);// sostituisce "Giallo"(atomi G,i,a,l,l,o) solo se seguito da “Verde” (asserzione)
    $replace2=preg_replace("/GialloVerde/","Nero",$str);//sostituisce "GialloVerde" (atomi G,i,a,...)
    echo "1:$replace1
    "
    //"NeroVerdeBiancoGialloRossoNeroVerdeGialloBlu"
    echo "2:$replace2
    "
    // "NeroBiancoGialloRossoNeroGialloBlu" 

    Regola 4
    La preg può contenere delle alternative separate da una barra verticale ‘|’; l’engine li esamina da sinistra a destra nell’ordine di apparizione. Quest’ordine di valutazione delle alternative ha un’estrema importanza nelle preg usate per fare una sostituzione. Un esempio in questo script:
    Codice PHP:
    $str="GialloVerdeBiancoGialloRossoGialloVerdeGialloBlu";
    $replace1=preg_replace("/GialloVerde|Giallo/","Nero",$str);
    $replace2=preg_replace("/Giallo|GialloVerde/","Nero",$str);
    echo 
    "1:$replace1
    "
    //"NeroBiancoNeroRossoNeroNeroBlu"
    echo "2:$replace2
    "
    // "NeroVerdeBiancoNeroRossoNeroVerdeNeroBlu" 
    Regola 5
    Un atomo può essere seguito da un quantificatore che indica quante volte l’atomo deve essere riscontrato in sequenza nella stringa
    Questi alcuni quantificatori
    * zero o più volte
    + una o più volte
    ? zero o una volta
    {n,} almeno n volte
    {n,m} almeno n volte ma non più di m volte

    Alcuni esempi:

    /abcx*d/ atomi “abc” seguiti da atomo “x” che si ripete 0 o più volte seguita atomo “d”; quindi ha riscontro in stringhe del tipo: “abcd”,”abcxd”,”abcxxd”, etc...

    /abcx{1,2}d/ trova riscontro solo in stringhe che contengono “abcxxd” oppure “abcxd”

    I quantificatori hanno un comportamento ‘ingordo’ cioè l’engine tenta di verificare l’atomo prima con il suo massimo di ripetizioni poi se fallisce con il suo massimo-1, poi massimo-2 e così via sino al minimo
    Esempio:
    /abcx{1,2}d/ tenta prima “abcxxd” e poi “abcxd”

    Per forzare un comportamento minimale (l’inverso di ingordo) il quantificatore deve essere seguito da ‘?’
    Questi alcuni quantificatori minimali
    *? zero o più volte
    +? una o più volte
    ?? zero o una volta
    {n,}? almeno n volte
    {n,m}? almeno n volte ma non più di m volte
    Questo un esempio:
    Codice PHP:
    $str="abcxxxxd abcxxxd abcxxd abcxd";
    $replace1=preg_replace("/abcx{3,4}/","ABC",$str);// ingordo
    $replace2=preg_replace("/abcx{3,4}?/","ABC",$str);// minimale
    echo "1:$replace1
    "
    //"ABCd ABCd abcxxd abcxd"
    echo "2:$replace2
    "
    // "ABCxd ABCd abcxxd abcxd" 
    I quantificatori in pratica generano delle alternative che vengono valutate in base alla regola 4 infatti:
    “/abcx{1,2}/” si puo scrivere come “/abcxx|abcx/” e
    “/abcx{1,2}?/” come “/abcx|abcxx/”;

    Regola 6
    Le parentesi tonde “(...)” sono metacaratteri e vengono usate per raggruppare una serie di atomi in un unico quantificatore oppure per raggruppare una serie di alternative
    Esempio:
    “/a(bc){1,2}/” vuol dire “a” seguito da “bc” che si ripete una o più volte quindi questa preg trova riscontro in stringe che contengono “abcbc” oppure “abc”;
    “/a(bc|de)/” trova riscontro in stringhe che contengono “abc” oppure “ade”.

    continua...

  2. #2
    Utente di HTML.it
    Registrato dal
    Jan 2003
    Messaggi
    34

    PILLOLINA sulle espressioni regolari (2/2)

    ....la continuazione

    Regola 7
    Le parentesi quadre sono metacaratteri, vengono usate per indicare delle alternative a carattere singolo oppure delle alternative composte da una serie di caratteri (è possibile fare un misto) il tutto è detto classe di caratteri
    esempio:
    “/a[bcdef]/” equivale ad “/a(b|c|d|e|f)/”
    “/a[b-f]/” è come l’esempio sopra (indica da ‘b’ ad ‘f’)
    “/[A-Za-z]/” indica qualsiasi carattere maiuscolo o minuscolo (da ‘A’ a ‘Z’ oppure da ‘a’ a ‘z’).

    Se come primo carattere tra le parentesi quadre appare un ‘^’ la classe di caratteri viene negata.
    “/a[^bc]/” una “a” seguita da qualsiasi carattere che non sia una “b” o una “c”.
    La classe di caratteri può contenere soltanto atomi.

    Regola 8
    Quando l’engine ha una preg con varie alternative, prova a riscontrarle una ad una, quando un’alternativa fallisce l’engine torna indietro e prova la seconda, se fallisce torna indietro e prova la terza e così via. Questo ‘tornare indietro e provare l’alternativa successiva’ viene fatto seguendo delle regole ben precise ed è detto: backtracking.

    Per comprendere il backtraching bisogna, prima di tutto, aver ben chiare le regole di cui sopra, e considerarle come delle funzioni che si richiamano a vicenda l’una con l’altra, ogni funzione restituisce il peso in caratteri (un semplicissimo numero intero) oppure false a secondo che il confronto abbia avuto successo oppure no; il chiamante valuta questo valore: se il valore è un peso continua altrimenti prova un’altra alternativa se non ci sono + alternative termina restituendo false al suo chiamante.

    Vediamo subito come funziona.
    Nell’esempio che segue sono coinvolte alcune delle regole che sopra ho descritto quindi immaginiamo di avere le seguenti funzioni che li racchiudono:
    regola1(); // l’engine scorre la preg da sinistra a destra
    regola2(); // l’engine scorre la stringa da sinistra a destra
    regola3(); // atomi e asserzioni
    regola5(); // quatificatori

    abbiamo una stringa “baxyde”
    ed una preg “/ax{1,2}y{1,2}/”

    analizziamo come si composta l’engine:

    Passo 1
    Si parte con regola2(); il puntatore viene posizionato prima del primo carattere della stringa, per cui (indicando con un punto ‘.’ Il puntatore) avremo “.baxyde”;
    Passo 2
    regola2() richiama regola1(); secondo la quale l’engine valuta la preg da sinistra a destra
    Passo 3
    regola1() richiama regola3() perché il primo carattere della preg è un atomo; per cui l’engine dovrà riscontrare l’atomo ‘a’ nella posizione corrente del puntatore stringa ma il confronto fallisce e l’engine fa backtracking ritornando alla regola chiamante cioè regola1() e gli restituisce false indicando appunto il fallimento.
    Passo 4
    Siamo tornati a regola1() che valutando il risultato ottenuto al passo precedente termina anch’essa restituendo false al suo chiamante
    Passo 5
    Siamo in regola2() il valore restituito dal passo 4 è false per cui tenta un’altra alternativa: il puntatore viene spostato un passo avanti ed avremo quindi “b.axyde” (il punto ’.’ è sempre il puntatore)
    Passo 5 come passo 2
    Passo 6
    Simile al passo 3: regola1() richiama regola3() ma questa volta il riscontro c’è, ed ha un peso in caratteri pari ad 1 (perché è stato riscontato un atomo) per cui regala3() restituisce il peso al chiamante indicando il successo.
    Passo 7
    Siamo tornati a regola1() il valore restituito dal passo precedente è un peso per cui un successo, si procede quindi a scorrendo la preg di ed incontriamo l’atomo ‘x’ con il quantificatore ‘{1,2}’, tale confronto verrà effetuato sulla nostra stringa non nella posizione attuale ma nella posizione attuale + 1 perché il passo 6 ha indicato che il peso del riscontro è pari ad 1 carattere.
    Passo 8
    regola1() richiama regola5() secondo la quale viene fatto un confronto ingordo, per cui l’engine tenta “xx” che fallisce.
    Passo 9
    siamo ancora in regola5() il passo precedente è fallito ma, prima di decretare il fallimento della funzione dobbiamo verificare le eventuali alternative: il modificatore era ‘{1,2}’ quindi, adesso, tentiamo un riscontro con ‘x’ ed abbiamo successo; Per cui regola5() termina restituendo il peso del riscontro che è 1;
    Passo 10
    siamo tornati a regola1() ed il passo precedente ha restituito peso uno, la funzione prosegue nel valutare la preg ed incontra ‘y{1,2}’ tale confronto (come al passo7) dovrà essere effettuato sulla nostra stringa nella posizione attuale + 2 (uno del passo 6 + uno del passo 9)
    Passo 11 come passo 8 ma con ‘yy’
    Passo 12 come passo 9 ma con ‘y’
    Passo 13
    siamo di nuovo a regola1() la preg è terminata per cui la funzione termina restituendo peso 3 (il totale) al chiamante
    Passo 14
    siamo in regola 2 il passo precedente ha restituito un peso per cui la preg è integralmente soddisfatta. Il puntatore di scorrimento era “b.axyde”, abbiamo un peso di 3 per cui l’engine termina restituendo “axy”;

    Questo è tutto! Ciao a tutti

  3. #3

    mmm....

    molto interessante... credo che ci studierò su... è da qualche tempo che desideravo un buon input di base riguardo alle espressioni regolari!

    grazie mille

    -Die-

  4. #4
    pillola molto figa!!:metallica
    w la topa

  5. #5
    bravo ferrot! :metallica

  6. #6

    AIUTO!!!

    sto cercando di costruirmi espressioni regolari mie... giusto x capire bene come funzionano...

    ho cercato di fare una roba tipo:

    eregi("/[0-9]{2}+\-+[0-9]{2}/",$stringa)

    che dovrebbe verificare che l'utente inserisca una stringa con formato ad esempio:

    88-32

    xchè mi restituisce questa roba??

    Warning: REG_BADRPT:irepetition-operator operand invalid in c:\programmi\easyphp\www\prove\espressioni_regolar i.php on line 10

    help me please... voglio capire!!!

    -Die-

  7. #7

    mmm...

    niente, ho capito... ora un'altra cosa mi assilla...

    vorrei che in una variabile ci debba essere una stringa che contiene solo lettere e numeri.

    ho fatto un

    if (ereg("[a-zA-Z0-9]{2,12}",$stringa)) {
    echo "$stringa è un nome utente valido";
    } else {
    echo "$stringa non è un nome utente valido";
    }

    ma non funziona

    -Die-

  8. #8
    Utente di HTML.it
    Registrato dal
    Jan 2003
    Messaggi
    34
    Ti faccio notare che:
    eregi() non è una funzione per espressioni regolari perl compatibili ma una funzione per espressioni regolari POSIX-estesa

    il corrispettivo di eregi("qualcosa",$str) è preg_match ("/qualcosa/i",$str) non conosco bene le differenze che ci sono tra POSIX-estesa e perl-compatibile per non sbagliare io uso sempre le perl-compatibili

    lo stesso mauale dice:

    Nota: Poichè utilizza espressioni regolari con sintassi compatibile con PERL, preg_match(), è spesso una alternativa più veloce a ereg().

  9. #9
    Utente di HTML.it
    Registrato dal
    Jan 2003
    Messaggi
    34
    Prova questa
    Codice PHP:
    if (preg_match("/^[a-zA-Z0-9]{2,12}$/",$stringa)) {
    echo 
    "$stringa è un nome utente valido\n";
    } else {
    echo 
    "$stringa non è un nome utente valido\n";


  10. #10

    mmm...

    scusate se vi rompo con i miei quesiti assurdi....

    esempio...

    io ho una stringa:

    "ciao -2- owiejfa -oiefn-"

    e vorrei che diventasse

    "ciao 2!! owiejfa oiefn!!"

    ossia...

    vorrei sostituire ogni pezzo delimitato da due meno (-) inserendo al suo posto, lo stesso pezzo, incluso tra i meno, seguito da due punti esclamativi...

    è solo un esempio.. è stupido ma... giusto x capire il risultato da ottenere...

    io pensavo una roba del tipo:
    $stringa=preg_replace("/-{da copiare}-/","{da copiare}!!",$stringa);

    capito a cosa mi riferisco?

    spero sia chiaro... e spero si possa fare :gren:

    grazie mille...

    -Die-

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.