chalda.it
28gen/1043

Guida alla sintassi delle espressioni regolari (con esempi)

espressioni regolari

È da un po' di tempo che meditavo la creazione di una guida alle espressioni regolari: in giro per la rete ce ne sono a bizzeffe, ma poche complete e pochissime quelle in italiano; inoltre scrivere una guida da la possibilità di ampliare le proprie conoscenze! Infatti scrivendola ho imparato cose di cui ignoravo l'esistenza!

Bisogna dire che molti preferiscono copiare ed incollare righe su righe di incomprensibili caratteri piuttosto che imparare questa strana sintassi, poiché a prima vista questa appare criptica ed incomprensibile e le espressioni sono solo lunghe serie di caratteri messi a casaccio senza un nesso logico!

Ma vedrete che non c'è nulla di difficile: basta un po' di elasticità mentale, un pizzico di memoria e soprattutto un buon manuale da consultare spesso :-D

Cercherò di utilizzare una linearità nella descrizione, anche se questo mi risulterà difficile poiché è complicato spiegare un singolo elemento senza utilizzarne altri.

A che cosa servono le espressioni regolari?

Le espressioni regolari sono molto utili nell'ambito della ricerca e della sostituzione. Immaginiamo di avere un testo storico enorme e di dover convertire tutte le date in formato americano (yyyy/mm/dd) in quello classico italiano...

Sarebbe un lavoraccio dover fare tutto il lavoro a mano! E probabilmente ci sfuggirebbero degli errori!

Ecco, con le espressioni regolari è possibile farlo in pochi caratteri! Con un risparmio di tempo, di errori e di fegato :-P

La sintassi: Uguale per tutti i programmi / linguaggi?

Solitamente si, in javascript e in perl la sintassi è simile, preg_replace di php utilizza la sintassi di perl, mentre ereg... beh, ereg ormai è deprecato.
Anche Ide e programmi di testo come vim, notepad++, Komodo edit, Dreamweaver, etc. supportano il search&replace con le espressioni regolari.
Diciamo che la sintassi potrebbe cambiare, ma non di molto. E comunque se imparate quella di perl potrete comunque cavarvela con qualsiasi altra variante :-D

Ma passiamo alla descrizione dettagliata di ogni singolo elemento:

 

I metacaratteri

Nelle espressioni regolari esistono diversi "caratteri speciali" dalle diverse funzioni

Meta Descrizione
. significa qualsiasi carattere ad eccezione di quelli che identificano una riga nuova (\n e \r per intenderci)

$testo = "espressioni regolari!";
preg_match_all('/./', $testo, $ris);
// Troverà tutti i caratteri
^ identifica l'inizio di una riga; inoltre all'inizio di un gruppo nega il gruppo stesso

$testo = "espressioni regolari!";
preg_match_all('/^./', $testo, $ris);
// Troverà solamente la lettera "E"
$ identifica la fine di una riga

$testo = "espressioni regolari!";
preg_match_all('/.$/', $testo, $ris);
// Troverà solamente "!"
| è una condizione OR

$testo = "espressioni regolari!";
preg_match_all('/a|i|u|o|e/', $testo, $ris);
// Troverà tutte le vocali
() le parentesi tonde identificano dei gruppi di caratteri
[] le parentesi quadre identificano intervalli e classi di caratteri
\ questo carattere annulla gli effetti del metacarattere successivo

$testo = "espressioni.regolari!";
preg_match_all('/\./', $testo, $ris);
// Troverà solo il punto

 

I quantificatori

I quantificatori, come dice il termine stesso, indicano quante volte ricercare una data sequenza di caratteri.

Classi Descrizione
* indica 0 o più occorrenze

$testo = "Espressioni, pesi, piume!";
preg_match_all('/s*i/', $testo, $ris);
// Troverà "ssi" di espressioni,
// "si" di pesi
// e "i" di piume
+ indica 1 o più occorrenze

$testo = "Espressioni, pesi, piume!";
preg_match_all('/s+i/', $testo, $ris);
// Troverà "ssi" di espressioni
// e "si" di pesi
? indica 1 o 0 occorrenze

$testo = "Espressioni, pesi, piume!";
preg_match_all('/s?i/', $testo, $ris);
// Troverà "si" e "i" di espressioni,
// "si" di pesi
// e "i" di piume
{n} ricerca esattamente n occorrenze; da ricordare che le parentesi grafe vengono considerate caratteri normali in tutti gli altri contesti

$testo = "ese, esse, essse, esssse!";
$testo = preg_replace('/es{2}e/', '*', $testo);
// Ora $testo sarà "ese, *, essse, esssse!"
{n,} ricerca minimo n occorrenze; vedi sopra

$testo = "ese, esse, essse, esssse!";
$testo = preg_replace('/es{3,}e/', '*', $testo);
// Ora $testo sarà "ese, esse, *, *!"
{n,m} ricerca minimo n occorrenze ma non superiori alle m; vedi sopra

$testo = "ese, esse, essse, esssse!";
$testo = preg_replace('/es{2,3}e/', '*', $testo);
// Ora $testo sarà "ese, *, *, esssse!"

 

I quantificatori "non golosi" (ungreedy)


Quasi tutti inciampano prima o poi in questo problema: se utilizzo una espressione del tipo /".*"/ troverò tutte le parole racchiuse tra doppi apici? Purtroppo no!
Questo perché i quantificatori normali sono "golosi" (in inglese greedy), cioè cercano l'occorrenza il più grande possibile.
Vediamo con un esempio:

$testo = 'class="pluto" id="pippo"';
preg_match_all('/".*"/', $testo, $ris);
// Troverà un'unica occorrenza:
// "pluto" id="pippo"

Come vedete non è il risultato sperato! Come fare quindi?
Basta aggiungere un punto interrogativo alla fine dei nostri quantificatori

$testo = 'class="pluto" id="pippo"';
preg_match_all('/".*?"/', $testo, $ris);
// Ora troverà "pluto" e "pippo" !

Questo vale per qualsiasi quantificatore descritto in precedenza!

 

Le classi e gli intervalli

 

Le classi determinano un elenco di caratteri, di classi di caratteri o di POSIX (vedi la sezione successiva) da ricercare. Vengono racchiusi tra parentesi quadre e possono essere seguiti dai quantificatori.

$testo = 'Questa è una stringa lunga lunga di esempio';
preg_match_all('/[aiuoe]{2}/', $testo, $ris);
// L'espressione ricercherà due vocali consecutive,
// quindi troverà "ue" e "io"

Per identificare un intervallo invece si utilizza il segno meno ( - ). Per esempio a-z identificherà tutti i caratteri minuscoli dalla a alla z, F-R i caratteri maiuscoli dalla F alla R, 0-5 i numeri da 0 a 5 e così via.

$testo = 'caratteri 16sdf456 e un colore esadecimale 94fa3c ';
preg_match_all('/[0-9a-f]{6}/', $testo, $ris);
// L'espressione ricercherà 6 caratteri che siano numeri o lettere dalla a alla f
// quindi troverà "94fa3c"

Il carattere ^, che se posto subito dopo la parentesi quadra aperta nega tutto l'intervallo, cioè indica di non ricercare i caratteri inclusi.

$testo = 'Questa è una stringa lunga lunga di esempio';
preg_match_all('/[^aiuoe ]{3}/', $testo, $ris);
// L'espressione ricercherà 3 lettere che non siano vocali o spazi
// quindi troverà solamene "str"

 

Le classi di caratteri e i POSIX

 

Le classi di caratteri e i POSIX servono per specificare una serie di caratteri allo stesso tempo, senza dover scomodare i gruppi.
Da ricordarsi che i POSIX in php devono essere racchiusi da una doppia parentesi quadra.

Classi Corrisponde a Descrizione
\w
[:word:]
[a-zA-Z0-9_] ricerca un carattere "parola" (w sta per word), cioè lettere, numeri e "_"

$testo = "[[Le_Regex sono_belle!!!]]";
preg_match_all('/\w+/', $testo, $ris);
// Troverà "Le_Regex" e "sono_belle"
\W [a-zA-Z0-9_] ricerca un carattere che non sia \w, cioè tutto quello che non è lettere, numeri o "_"

$testo = "[[Le_Regex sono_belle!!!]]";
preg_match_all('/\w+/', $testo, $ris);
// Troverà "[[", " " e "!!!]]"
\d
[:digit:]
[0-9] ricerca un numero (d sta per digit)

$testo = "123 stella! 456 cometa!";
preg_match_all('/\d+/', $testo, $ris);
// Troverà "123" e "456"
\D [^0-9] l'opposto di \d, ricerca qualsiasi cosa che non sia un numero

$testo = "123 stella! 456 cometa!";
preg_match_all('/\D+/', $testo, $ris);
// Troverà " stella! " e " cometa!"
// anche gli spazi!!!
\s
[:space:]
[ \t\r\n\v\f] ricerca uno spazio, comprese tabulazioni e caratteri di fine riga

$testo = "manuale sulle
          espressioni regolari!";
$testo = preg_replace('/\s+/', '', $testo);
// Ora testo sarà manualesulleespressioniregolari!
\S [^ \t\r\n\v\f] l'inverso di \s, ricerca qualsiasi cosa che non sia uno spazio, una tabulazione o dei caratteri di fine riga

$testo = "Descrizione di:\S!";
preg_match_all('/\S+/', $testo, $ris);
// Troverà "Descrizione" e "di:\S!"
[:alnum:] [a-zA-Z0-9] Ricerca caratteri alfanumerici, senza "_"

$testo = "[[Le_Regex 123 sono_belle!!!]]";
preg_match_all('/[[:alnum:]]+/', $testo, $ris);
// Troverà "Le","Regex", "123",
// "sono" e "belle"
[:alpha:] [a-zA-Z] Ricerca caratteri alfabetici

$testo = "[[Le_Regex 123 sono_belle!!!]]";
preg_match_all('/[[:alpha:]]+/', $testo, $ris);
// Troverà "Le","Regex", "sono" e "belle"
[:blank:] [ \t] ricerca solo spazi e tabulazioni

$testo = "questa è una prova
	con spazi e tabulazioni";
$testo = preg_replace('/[[:blank:]]+/', '', $testo);
/* $testo ora sarà:
questaèunaprova
conspazietabulazioni
*/
[:lower:] [a-z] ricerca lettere minuscole

$testo = "ESPRESSIONI regolari";
preg_match_all('/[[:lower:]]+/', $testo, $ris);
// Troverà "regolari"
[:upper:] [A-Z] ricerca lettere maiuscole

$testo = "ESPRESSIONI regolari";
preg_match_all('/[[:upper:]]+/', $testo, $ris);
// Troverà "ESPRESSIONI"
[:graph:] [\x21-x7E] ricerca tutti i caratteri visibili a video della tabella ascii non estesa, dal numero 33 (!) al 126 (~).

$testo = "Espressioni regolari
	però divertenti!!!";
preg_match_all('/[[:graph:]]+/', $testo, $ris);
// Troverà "Espressioni", "regolari", "per", "divertenti!!!"
[:print:] [\x20-x7E] ricerca tutti i caratteri visibili a video della tabella ascii non estesa, dal numero 32 (spazio) al 126 (~).

$testo = "Espressioni regolari
	però divertenti!!!";
preg_match_all('/[[:print:]]+/', $testo, $ris);
// Troverà "Espressioni regolari", "per", "divertenti!!!"
[:punct:] - ricerca tutti i caratteri di punteggiatura come -!"#$%&'()*+,.\/:;<=>?@[]^_`{|}~

$testo = '(F@^ra*s--e s|,e!n/.z\\a la p`u"t>?eg:g;i++at)]ur"a)';
$testo = preg_replace('/[[:punct:]]+/', '', $testo);
// Ora $testo sarà "Frase senza la punteggiatura"
[:cntrl:] [\x00-x1F\x7F] ricerca solo i caratteri di controllo

 

I modificatori

 

Ogni operazione di ricerca può utilizzare vari modificatori, che, come dice il nome stesso, possono modificare i criteri di ricerca predefiniti.
Questi modificatori devono essere posizionati alla fine della stringa di ricerca, subito dopo il carattere di limitazione.
È possibile combinare più effetti accodando senza spazi i modificatori (per esempio: /imsu applicherà tutti e 4 gli effetti sotto descritti).

Mod. Descrizione
i la ricerca diventa case-insensitive, cioè maiuscole e minuscole vengono considerate uguali

$testo = "Le Espressioni Regolari sono regolari?";
preg_match_all('/regolari/i', $testo, $ris);
// Troverà sia "regolari" che "Regolari"
m le ricerca verrà considerate "per riga", cioè le ancore tipo "^" e "$" verranno applicate per ogni riga di testo

$testo = 'Espressioni Regolari
Espressioni in perl
Espressioni php';
preg_match_all('/^Espressioni/m', $testo, $ris);
// Troverà tutte e 3 le "Espressioni"
// e non solo la prima
s il testo viene considerato un'unica riga e "." ora identifica anche i caratteri di fine riga, che normalmente non troverebbe

$testo = 'Espressioni Regolari
Espressioni in perl
Espressioni php';
preg_match('/perl.Espressioni/s', $testo);
// la ricerca avrà successo
u vengono abilitati i caratteri Unicode estes, come \x{10FFFFF}

$testo = '紫の触手、緑の触手';
preg_match('/\x{89e6}\x{624b}/u', $testo, $ris);
// la ricerca avrà successo
U attiva l'opzione ungreedya tutti i quantificatori

$testo = 'class="pluto" id="pippo"';
preg_match_all('/".*"/U', $testo, $ris);
// equivale a /".*?"/ troverà sia "pluto" che "pippo"

 

Le ancore

Le ancore identificano la posizione in cui ricercare il nostro testo.

Ancora Descrizione
^ identifica l'inizio della stringa; con il modificatore /m identifica l'inizio di ogni riga

$testo = 'Questo è un esempio
sulle Espressioni Regolari
nella sintassi di perl';
preg_match_all('/^[\w]+/m', $testo, $ris);
// la ricerca troverà "Questo", "sulle" e "nella"
$ identifica la fine della stringa; con il modificatore /m identifica la fine di ogni riga

$testo = 'Questo è un esempio
sulle Espressioni Regolari
nella sintassi di perl';
preg_match('/[\w]+$/m', $testo, $ris);
// la ricerca troverà
// "esempio", "Regolari", "perl"
\A similmente a ^, identifica solo l'inizio della stringa, anche se è presente il modificatore /m

$testo = 'Questo è un esempio
sulle Espressioni Regolari
nella sintassi di perl';
preg_match_all('/\A[\w]+/m', $testo, $ris);
// la ricerca troverà "Questo"
\Z similmente a $, identifica solo la fine della stringa, anche se è presente il modificatore /m

$testo = 'Questo è un esempio
sulle Espressioni Regolari
nella sintassi di perl';
preg_match_all('/[\w]+\Z/m', $testo, $ris);
// la ricerca troverà "perl"
\b indentifica il punto tra due caratteri che siano \w a sinistra e non \w a destra

$testo = 'condor daino dingo elefante';
preg_match_all('/\bd\w+/', $testo, $ris);
// la ricerca troverà solo le parole che iniziano
// con la lettera d, cioè "daino" e "dingo"
\B identifica l'opposto di \b

$testo = 'condor daino dingo elefante';
preg_match_all('/\Bd\w+/', $testo, $ris);
// la ricerca troverà solo una serie di caratteri
// che iniziano con d la quale non sia l'inizio di
// una parola, in questo caso "dor"

 

I caratteri speciali

 

Chi ha un po' di conoscenza di php o di perl avrà già avuto a che fare con quei segnaposto che identificano dei caratteri speciali, come quelli di fine riga o le tabulazioni. Tali segnaposto iniziano tutti con il carattere \
Ecco un elenco molto più che dettagliato, da sottolineare l'importanza di \Q!!!

Segnaposto Carattere corrispondente
\t tabulazione (HT, TAB)
\n fine riga (LF, NL)
\r ritorno a capo (CR)
\Q disabilita qualsiasi metacarattere presente fino a \E
molto utile per inserire delle variabili nella stringa

$variabile = '[\w\s]+';
$testo = "Questo testo [\w\s]+[\w\s]+ ha regex al suo interno!";

$testo1 = preg_replace('/'.$variabile.'/', '', $testo);
// $testo1 senza sarà "[\\]+[\\]+!"

$testo2 = preg_replace('/\Q'.$variabile.'\E/', '', $testo);
// $testo2 invece sarà "Questo testo  ha regex al suo interno!"
\E vedi sopra
\nnn carattere in forma ottale dove n è un numero da 0 a 7
\xnn carattere in forma esadecimale dove n è un numero... esadecimale
\f form feed (FF)
\a alarm/bell (BEL)
\e escape (BEL)

 

I gruppi

 

I gruppi vengono racchiusi dalle parentesi tonde e diventano essenziali nel momento della sostituzione, poiché è possibile richiamarli. Un esempio per chiarire tutto:

$testo = "Questo è una data formato mysql: 2010-01-28";
$testo = preg_replace('/(\d{4})-(\d{2})-(\d{2})/', 'Questa è una data in formato europeo: $3/$2/$1', $testo);
// ora $testo sarà "Questa è una data in formato europeo: 28/01/2010"

Come vedete l'espressione contiene tre gruppi e nella sostituzione compaiono dei dollari seguiti da un numero: questo numero rappresenta il testo trovato dal gruppo corrispondente. Così $1 identificherà il primo gruppo, $2 il secondo e così via.

Per essere fiscali è possibile utilizzare \1 e \2 invece che $1 e $2, ma ve lo sconsiglio in quanto le barre dentro una stringa devono essere precedute da un'altra barra e questo rende tutto meno leggibile

$testo = "Questo è una data formato mysql: 2010-01-28";
$testo = preg_replace('/(\d{4})-(\d{2})-(\d{2})/', 'Questa è una data in formato europeo: \\3/\\2/\\1', $testo);
// ora $testo sarà "Questa è una data in formato europeo: 28/01/2010"

Nei gruppi inoltre è possibile aggiungere un'espressione logica "OR", cioè poter ricercare una serie di caratteri oppure un'altra

$testo = "Si dice ha piovuto o è piovuto in italiano?";
$testo = preg_replace('/\s+((ha|è)\s+piovuto)\s+/', ' è nevicato ', $testo);
// L'espressione cercherà "ha piovuto" oppure "è piovuto" seguiti o preceduti da spazi;
// $testo ora sarà "Si dice è nevicato o è nevicato in italiano?"

Questa funzione ritornerà sia "ha piovuto" che "è piovuto". Ma fate attenzione , poiché anche in questo caso le parentesi tonde rappresentano un gruppo e quindi verrà considerato nelle variabili di sostituzione, in questo caso $1 conterrà "ha piovuto" o "è piovuto" e $2 "ha" o "è".
Qui non sempra un problema, ma nelle espressioni più complesse ricercare cose non necessarie complica orrendamente le cose. Come fare allora? Basta utilizzare i gruppi passivi, aggiungendo un "?:" subito dopo la parentesi tonda aperta:

$testo = "Si dice ha piovuto o è piovuto in italiano?";
$testo = preg_replace('/\s+((?:ha|è)\s+piovuto)\s+/', ' è nevicato ', $testo);
// L'espressione cercherà "ha piovuto" oppure "è piovuto" seguiti o preceduti da spazi;
// $testo ora sarà "Si dice è nevicato o è nevicato in italiano?"

Se analizzate il risultato ora conterrà solamente "ha piovuto" e "è piovuto"

 

Le asserzioni

 

Ho lasciato appositamente per ultime le asserzioni, visto che la maggior parte delle persone ha molta difficoltà ad assimilarle. Però una volta imparate le userete spesso e volentieri!

Esponiamo un problema: è possibile ricercare solo quelle parole che iniziano con la lettera "c" ma che la seconda lettera non sia una vocale? Certo, basta utilizzare le asserzioni! In pratica sono degli elementi di controllo che vengono applicati alle nostre ricerche.
Inoltre tutte le asserzioni sono passive, cioè, come spiegato prima, non vengono aggiunte fra le variabili di ricerca.

È un po' complicato da spiegare, ma vedrete che con gli esempi qui sotto tutto risulterà più chiaro!

Asserzione Descrizione
(?=pattern) asserzione lookahead positiva, cioè valida l'espressione precedente solo se la condizione patternè verificata.

$testo = "cane crotalo canarino criceto cervo";
preg_match_all('/\b(c(?=[aiuoe])\w+)/', $testo, $ris);
// L'espressione cercherà le parole che iniziano con la c solo se sono seguite da una vocale,
// per la precisione "cane", "canarino" e "cervo";
(?!pattern) asserzione lookahead negativa, cioè valida l'espressione precedente solo se la condizione patternnon è verificata.

$testo = "cane crotalo canarino criceto cervo";
preg_match_all('/\b(c(?![aiuoe])\w+)/', $testo, $ris);
// L'espressione cercherà le parole che iniziano con la c solo se non sono seguite da una vocale,
// per la precisione "crotalo" e "criceto";
(?<=pattern) asserzione lookbehind positiva, cioè valida l'espressione successiva solo se la condizione patternè verificata.

$testo = "cesto pasto fasto pesto costo";
preg_match_all('/(\w+(?<=a)sto)/', $testo, $ris);
// cercherà le parole che finiscono con "sto" la cui lettera precedente sia "a"
// quindi troverà "pasto" e "fasto";
(?<!pattern) asserzione lookbehind negativa, cioè valida l'espressione successiva solo se la condizione patternnon è verificata.

$testo = "cesto pasto fasto pesto costo";
preg_match_all('/(\w+(?
(?>pattern) sottoespressione indipendente, cioè l'espressione viene considerata singolarmente senza considerare altre cose.

$testo = "aaaaaaaaaaaaab";
preg_match('/(a*)ab/', $testo, $ris);
// Questa ricerca avrà successo
preg_match('/(?>a*)ab/', $testo, $ris);
// Questa espressione non avrà successo poichè (?>a*) verrà considerata singolarmente e raggrupperà tutte le a, quindi non potrà più trovare il successivo "ab"

 

Conclusioni


Bene, ora avete una infarinatura sulle espressioni regolari!
In futuro aggiornerò questa guida aggiungendo esempi e nuove descrizioni, quindi vi consiglio di aggiungerla ai preferiti!
Ovviamente se avete cose da aggiungere potete farlo nei commenti!

Be Sociable, Share!
Commenti (43) Trackback (0)
  1. Bella questa guida!
    E’ già nei preferiti!

  2. Salve
    ho un piccolo problema di lavoro
    ma sulla shell sono alle prome armi
    e avrei bisogno di un suggerimento

    in linux
    come faccio a verificare se un dato file
    contiene solo numeri ??
    sarei molto grato
    grazie.

  3. Ciao Silvio!
    Per la ricerca di file di soli numeri devi utilizzare il comando “find”:

    find . -regex ".*/[0-9]+"

  4. grazie mi chiedevo :
    questa sintassi mi restituisce i file con il nome in forma numerica o con il
    contenuto ?
    sarebbe tipo :

     lista=$(ls -1 pippofile*)
                   for index in $lista 
                   do
                   find .-regex".*/[0-9]+" $index
                   stato=$?
                   done

    e’ cosi? come controllo il singolo file ?? grazie tante

  5. Beh, potresti invece fare una cosa del genere:

    lista=$(find /cartella/ -regex ".*/pippofile[0-9]+" )
                   for index in $lista 
                   do
                   echo $index
                   done
    

    In $lista avresti tutti i file contenenti numeri presenti nella cartella :)

  6. la provo subito grazie tante Chalda

  7. Ottima guida: semplice, completa, schematica e sinottica, piena di esempi chiari e facili.

    Peccato per un piccola svista proprio nella parte iniziale, nell’esempio sull’uso del meta-carattere $, che rischia di disorientare i più inesperti (i cosiddetti neofiti). La versione corretta dell’esempio è ovviamente:

    preg_match_all(‘/.$/’, $testo, $ris);

    Questo è quello che ho trovato a colpo d’occhio, ad una prima scorsa veloce. Non escludo quindi la presenza di altri errori (magari più importanti), ma ho ritenuto di segnalartelo subito, a causa dell’impatto psicologico negativo che ha avuto su me stesso (anche se poi leggendo il seguito mi sono ricreduto). Vale quindi la pena di correggerlo al più presto!
    Naturalmente, se avrò tempo e voglia di analizzare a fondo tutto il documento, non mancherò di inviarti miei eventuali commenti ulteriori.

    Personalmente ho già una buona esperienza sull’argomento e non mi mancano certo guide e tutorial, tutti in inglese, ed anche ottima guida tascabile in italiano, trovata per caso in libreria un mese fa’ a pochi euro (se ti interessa ti farò sapere i dettagli), che ancora devo leggere (spiega anche le differenze fra Perl, PHP, JavaScript, etc., con esempi).

    Mi sono imbattuto nel tuo sito perchè stavo cercando una guida semplice e valida in italiano per un amico (possibilmente gratuita), e credo francamente di averla trovata proprio qui.

    Complimenti e buon proseguimento.

    Valerio.

  8. Grazie della segnalazione, ho corretto l’errore di “copiaincollatura” :-)
    In inglese ci sono molte guide più complete, io di solito mi baso su http://www.regular-expressions.info/ , però parla in modo alquanto complesso per uno che si deve avvicinare alle espressioni regolari.
    Grazie dei complimenti e lieto di esserti stato d’aiuto :P

  9. 1 $testo = ‘Questa è una stringa lunga lunga di esempio’;
    2 preg_match_all(‘/[aiuoe]{2}/’, $testo, $ris);
    3 // L’espressione ricercherà due vocali consecutive,
    4 // quindi troverà “ue” e “un”

    correzione:
    quindi troverà “ue” e “io”

  10. Comunque grazie a questa guida sto imparando questo argomento, è veramente un casino impararli, in internet è tutto in inglese e le poche guide in italiano che ci sono partono subito in quarta e non si capisce niente. Li sto imparando meglio qui che nel librone da 900 pagine che ho! :P

  11. Grazie della segnalazione e dei complimenti, sono contento di esserti stato utile!

  12. Ciao a tutti,
    devo costruire un’espressione regolare che mi trova delle stringe racchiuse tra parentesi graffe, al fine di eliminarle.
    Per esempio:
    la mia stringa iniziale è:
    [code]Testo bla bla bla {pippo} 2 bla bla bla {topolino} ciao ciao[code];

    quella finale deve diventare
    [code]Testo bla bla bla 2 bla bla bla ciao ciao[code];

    Qual è l'esatta espressione regolare da utilizzare nella funzione eregi_replace?

  13. Allora… ti sconsiglio di utilizzare eregi, in quanto è deprecato ( http://php.net/manual/en/function.ereg.php ), meglio usare preg_replace!
    Puoi comunque utilizzare la seguente espressione:

    $stringa = preg_replace('/{(.*?)}/', '', $stringa);
    // con ereg_replace: (deprecato e lento):
    $stringa = ereg_replace('{[^}]*}','',$stringa);
    

    Ereg non supporta gli ungreedy, quindi la sintassi è un attimo diversa.
    Comunque ti rinnovo il suggerimento di dimenticare ereg per passare a preg :P

  14. Bravissimo, guide così se ne trovano davvero poche in giro!

    Ti segnalo un errore di copiatura nell’asserzione lookbehind negativa.
    Hai copiato

    preg_match_all('/(\w+(?<!--a)sto)/', $testo, $ris);

    Mentre dovrebbe essere

    preg_match_all('/(\w+(?<!a)sto)/', $testo, $ris);

    Ancora complimenti,
    Luca Bartoli

  15. Io mi sono letto tutta la guida ma c’è una cosa che non riesco proprio a fare

    Mettiamo il caso di questo esempio

    Io ho una stringa lunghissima dove ci sono molte parole tipo “details”
    Vorrei che il preg_match trovasse tutto il testo che sta tra ogni “details” e il più vicino punto “.”

    Esempio
    $stringa = “ciao a tutti details e in ogni ciao a tutti. perchè ciao details che ciao io devo fare. il modo che details è sempre.”;

    Dovrei estrapolare delle variabili che siano
    $var1 = ” e in ogni ciao a tutti”;
    $var2 = ” che ciao io devare”;
    $var3 = ” è sempre”;

    Mi sto dannando con questo preg_match e non riesco proprio a cavarne piede

    Ringrazio tantissimo a chi mi dà una mano in questo!
    Ciao grazie!

  16. Ciao Alessio,
    La cosa è semplice:

    $stringa = 'ciao a tutti details e in ogni ciao a tutti. perchè ciao details che ciao io devo fare. il modo che details è sempre.';
    preg_match('/details(.*?)\./', $stringa, $sub);
    print_r($sub);
    

    In pratica ricerchi tutto quello che c’è tra details ed un punto.
    Fai attenzione al ? (che identifica la ricerca ungreedy) e l’escape (\) prima del punto

  17. ciao…
    innanzitutto complimenti per la guida…
    avrei una domanda:

    mettiamo che abbia la stringa:

    $stringa =”questa stringa contiene un ritorno

    a capo.”

    come dovrei scrivere l’espressione regolare che mi dia true confrontandola con la stringa

  18. ti ringrazio comunque ma ho già risolto…
    io scrivevo l’espressione correttamente… ma misteriosamente non funzionava… forse qualche virgola fuoriposto…

    ancora complimenti per la guida!

  19. ciao,
    complimenti per la guida, tuttavia non ho ben capito come fare per le lettere accentate.
    devo controllare un nome, quindi voglio accettare lettere, lettere accentate, apostrofi e spazio.
    ho provato in questa maniera, utilizzando i codici ASCII, ma non funziona:
    preg_match_all(‘/[\x27x41-x5Ax60-x7Ax80-x9AxA0-xA5xB5-xB7xD2-xD4xD6xE0-xE5xE9-xEBxEF ]/’, $nome,$out).
    hai qualche idea?
    grazie mille

  20. Complimenti per la guida mi è stata molto utile. Posso porti un quesito?
    Ho un problema che mi sta facendo impazzire ma sono certo che mi sto perdendo in un bicchiere d’acqua.

  21. Ciao,
    complimenti per la guida.

    Vorrei farti una domanda: è possibile utilizzare le espressioni regolari per rimpicciolire o ingrandire una immagine senza ricorrere alle librerie GD? Se sì, come?

    In dettaglio:
    con una query a mysql recupero dei valori che sono testo e immagine con tutti i tag del caso. L’immagine nel tag html ha i width e l’height valori predeterminati.

    Una volta che recupero il testo e l’immagine vorrei che quest’ultima assuma dei valori width e l’height diversi.

  22. Ciao!

    Grazie per questo! Questo mi ha aiutato molto :)

    Alex

  23. Ciao a tutti,
    vi chiedo un consiglio… devo ricercare del testo in una pagina html tipo @aaa bbb ccc@ oppure @aaa bbb@
    devo trasformarlo in aaa bbb ccc (nel primo caso) oppure aaa bbb

    Non ci salto fuori :)

  24. Ciao Marco,
    suppongo che tu indenda in php…
    Per rimpiazzare il testo pasta che tu utilizzi preg_replace:

    $testo = preg_replace('/@(.*?)@/', '$1', $testo);
    

  25. Ciao,
    sto eseguendo un url-rewrite tramite il file .htaccess con il seguente codice
    ^news/([a-z._-]+)/([0-9]+).html$

    Ora devo implementare l’espressioni regolari permettendo gli ” e caratteri speciali come posso fare?
    Vi ringrazio in anticipo :)

  26. Ciao Simone,
    Per i caratteri speciali è sufficiente aggiungere un backslash (\) prima.
    Per esempio “*” diventa “\*”.
    Ciao

  27. Ciao, e grazie per la guida.
    E’ possibile unire più espressioni come [:BLANK:] e [:punct:]
    grazie di nuovo

  28. Ciao Hurry,
    Certo, è possibile utilizzare quante più classi si vogliono.
    Basta utilizzarle seguendo la sintassi corretta! :P

  29. ciao, mai vista una guida cosi chiara e precisa come questa. credo che verrò più spesso a trovarti :)

  30. Fantastico :)
    Avevo bisogno di creare un tag personalizzato per contenere facilmente un parametro di un indirizzo Web, e il testo di quell’indirizzo… Qualcosa di simile:

    [CICCIO:numero]testo[/CICCIO]
    

    Da trasformare in:

    testo>/a>
    

    Ci ho impiegato 15 minuti a capire da zero come si fa… Grazie per l’aiuto :)
    Ecco la mia soluzione:

    
    function myBBCODE($testo) {
    	$testo = preg_replace(
    		'/\[ciccio:([0-9]+)\]([a-z0-9 \!\?\(\)\-]+)*?\[\/ciccio\]/i',
    		'$2',
    		$testo
    	);
    	return $testo;
    }
    $text	= "[ciccio:123456789]Funziona questo codice?[/ciccio] [ciccio:123]Boh![/ciccio]";
    echo "Originale: $text ";
    echo "Codificato: " . myBBCODE($text);
    

  31. Ciao
    ho tanti file in xml dove devo eliminare del testo composto da attributo più data.
    Di solito uso notepad++ ma in questo caso la data non sempre è la stessa e credo sia necessario usare le espressione regolari.
    La stringa che devo eliminare è:
    datavig=”20021001″
    Quale espressione regolare devo utilizzare per i numeri?
    Grazie e complimenti
    morena

    Grazie

  32. Ciao
    mi sa che mi sono complicato la vita… è la prima volta che affronto questo tipo di espressione.
    Questo è il mio pattern:

    ho dei nomi presi da un db e non voglio far visualizzare tutta la stringa che ha prefisso [Migra_] o [migra_], ho cominciato ad applicare e.. mi sono perso!
    Qualcuno può aiutarmi?
    Grazie

  33. Ciao Luca,
    In questo caso ti conviene direttamente filtrare i risultati tramite query, aggiungendo una clausola where “NOT LIKE ‘migra%’ ”
    Ciao,
    Chalda

  34. Ciao Morena,
    l’espressione semplificata è questa:
    datavig=’[\d]{8}’
    Ciao,
    Chalda

  35. Ciao
    grazie della risposta ma la query è una query ldap e mi ritorna un array e non so se si può applicare la clausola sql, quindi avevo pensati di filtarre l’array.
    luca

  36. Allora dovresti utilizzare qualcosa del tipo:

    $lista_filtrata = array();
    foreach($array as $row){
        if (!preg_match('/^migra_/i', $row)){
            $lista_filtrata[] = $row;
        }
    }
    

    In questo modo nell’array $lista_filtrata avresti tutte le righe che non iniziano per migra o Migra.

  37. Grazie!
    ho applicato il filtro e… prometto che studierò di più!

  38. Guida inserita tra i preferiti… anche se nel mio caso, a parte la sintassi, avrei bisogno di maggiori esempi pratici.
    Nello specifico ho bisogno di poter ricercare (e solo eventualmente modificare) del testo che si trova in una specifica colonna e/o in un range specifico di colonne.
    Testo di esempio:
    1234567890
    1234567890
    1234567890
    1234567890

    Risultato da ottenere
    1234EF890
    1234EF890
    1234EF890
    1234EF890

    Con editors quali SPF è possibile dare questo comando: C “56″ EF” 5 6 ALL (ossia Change stringa1 con stringa2 tra le posizioni 5 e 6 del testo… tutte le occorrenze … semplice vero?).

    Ovviamente dovrebbe essere possibile sostituire anche con stringhe di diversa dimensione… es 56 con PIPPO o con 0 etc.

    Visto che Notepad++ NON mette a disposizione un campo “position” o “column” o “range” durante la ricerca del testo, l’unica è ricorrere alle espressioni regolari… sempreché siano “comode” allo scopo.

    Si può avere un esempio specifico per questi casi ?
    Sarebbe bello se eventualmente venisse scritto un plugin di ricerca “avanzata” che consenta appunto di “generare” ed “eseguire” l’espressione regolare di ricerca in base ai parametri indicati… sarebbe più alla portata di qualsiasi utente (bisogna ammettere che le espressioni regolari non sono poi tanto “intuitive”).

    Grazie.

  39. Ciao Roberto,
    se il testo da modificare è tutto uguale e nella stessa posizione la cosa più semplice da fare con notepad++ è selezionare tutte le righe con il mouse tenendo premuto il tasto maiuscolo e poi editarle tutte assieme :)
    Questa funzionalità è utilissima ma non è nota a molti :)

  40. Ciao chalda,
    in realtà quella funzionalità la conosco benissimo e la utilizzo (ma solo quando è possibile farlo), come spiegato però vorrei poter RICERCARE del testo in una specifica posizione (colonna) e/o in un range (es: da pos. 6 a pos 15) e SOLO quando viene trovata contarla e/o sostituirla con altro testo.
    Capirai che se devo sostituire ad esempio PIPPO con PLUTO ho tre righe così:
    12345PIPPO12345
    123456789012345
    1234PIPPO012345
    PIPPO6789012345
    123456PIPPO2345

    E volessi sostituire PIPPO con PLUTO ma SOLO se è presente nel range di colonne 6-15 dovrei poter ottenere questo:
    12345PLUTO12345
    123456789012345
    1234PIPPO012345
    PIPPO6789012345
    123456PLUTO1234

    Come fai a fare una cosa del genere con mouse e tasto maiuscolo? (O forse sarebbe meglio di re tasto ALT).

    Sarebbe stato utile anche poter selezionare il testo nel range di colonne desiderato e poi richiedere la find o la sostituzione “nella selezione”, ma notepad++ NON lo consente.

    Da qui l’esigenza di comprendere bene l’utilizzo delle espressioni regolari… che potrebbero essere l’unica alternativa, ma anche se potentissime, NON sono l’ideale per poter “favorire” l’utilizzo di notepad++ o altri editor da parte di utenti meno smaliziati (e pensa che io non sono tra gli utenti meno smaliziati :-) ).

    Tu riesci a fare un conteggio ed eventualmente una sostituzione di quei casi che ti ho fatto vedere ?

    Ovviamente sarebbe stato TANTO MEGLIO aggiungere alla schermata di cerca o sostituisci dell’editor, anche una casella Da Posizione a Posizione… molto più inuitivo non trovi?

    Ciao e grazie.

  41. La guida è fatta bene, complimenti solo che i modificatori, i quantificatori etc.. compaiono sempre in maiuscolo.
    Questo perchè nel css c’è l’istruzione “text-transform: uppercase;” e quindi solo dal sorgente è possibile capire se sono maiuscole o minuscole.
    Es.
    \B indentifica il punto tra due caratteri che siano \w a sinistra e non \w a destra

    \B identifica l’opposto di \b

    Vedi esempio »

  42. Ti vorrei fare i miei complimenti !! Finalmente ho trovato una guida molto chiara alle espressioni regolari, che forse comincio a capire per la prima volta.

    Grazie !!

  43. la guida se non sbaglio ha un errore:
    il quantificatore * ritorna anche la “i” di espressioni


Leave a comment

I trackback sono disattivati.