PDA

Visualizza la versione completa : [regularExpression] dubbio importante


toni00t
22-03-2014, 12:10
ciao ho un grosso problema con le regular expression :dhò::dhò::dhò:

dati i file nella dir :


1.txt
a
a.*
appppppppppj.txt
arpiero.txt
a.txt
col.txt
cool.txt
coooooooool.txt
il ppppp ddsa l.txt
kola.txt
p2
pall.txt
.....


il comando ls | grep a.*
non mi restituisce nulla , mentre io gli sto dicendo a seguito da qualsiasi carattere ripetuto 0 o più volte

mentre
ls | grep "a.*" restituisce 9 risultati


a
a.*
appppppppppj.txt
arpiero.txt
a.txt
il ppppp ddsa l.txt
kola.txt
pall.txt




e ls | egrep "a.{3}" restituisce 6 risultati



appppppppppj.txt
arpiero.txt
a.txt
il ppppp ddsa l.txt
kola.txt
pall.txt



per quale motivo sono costretto a mettere il double quoting con le regular expression? quando è obbligatorio usarlo?
perchè io impongo a grep 3 occorrenze del carattere che precede e lui mi trova ad esempio arpiero.txt che di occorrenze di r n ha solo una ?
quando scrivo una regular expression i metacaratteri della shell perdono il loro significato no? es * nella shell significa qualsiasi stringa, mentre nella regular expression
qualsiasi occorrenza del carattere che precede
grazie

MItaly
22-03-2014, 12:39
quando scrivo una regular expression i metacaratteri della shell perdono il loro significato no?
No. La shell non sa nulla di grep o egrep, se non fai quoting applicherà il normale globbing (http://tldp.org/LDP/abs/html/globbingref.html), espandendo * e altri caratteri magici; a grep non arriverà il tuo pattern, ma i nomi dei file già espansi dalla shell.
Per "bloccare" il globbing devi usare gli apici singoli o doppi.

toni00t
22-03-2014, 14:58
No. La shell non sa nulla di grep o egrep, se non fai quoting applicherà il normale globbing (http://tldp.org/LDP/abs/html/globbingref.html), espandendo * e altri caratteri magici; a grep non arriverà il tuo pattern, ma i nomi dei file già espansi dalla shell.
Per "bloccare" il globbing devi usare gli apici singoli o doppi.


ciao , grazie della risposta : 1) se la shell non sa nulla di grep e regular expression , e se è necessario fare il quoting , a cosa serve usare la sbarra rovesciata \ davanti a caratteri come * \ . ect ????? inoltre , come si fa a far in modo che grep interpreti in modo letterale i caratteri * \ ect , senza la shell prima li espanda considerandoli metacaratteri?

MItaly
22-03-2014, 15:17
ciao , grazie della risposta : 1) se la shell non sa nulla di grep e regular expression , e se è necessario fare il quoting , a cosa serve usare la sbarra rovesciata \ davanti a caratteri come * \ . ect ????? inoltre , come si fa a far in modo che grep interpreti in modo letterale i caratteri * \ ect , senza la shell prima li espanda considerandoli metacaratteri?
Il problema è che ci sono due livelli di escaping.

Se non metti la stringa tra virgolette, la shell fa globbing a meno che i caratteri speciali non siano preceduti da \. In questo caso "passano" direttamente al comando, cosa di cui puoi avere prova facendo qualche test con il comando echo:


matteo@teolapkubuntu:~/py/test$ echo *
backup.py backup.pyc
matteo@teolapkubuntu:~/py/test$ echo \*
*

Tuttavia, * a sua volta ha un significato speciale nelle regex; se vuoi matchare * in una regex, deve arrivare a grep come \*, motivo per cui dovresti fare un doppio escaping, dato che sia il backslash che l'* devono essere escapati perché la shell non li tocchi:


matteo@teolapkubuntu:~/py/test$ echo \\\*
\*


In questa maniera rischi di ritrovarti con una quantità improbabile di backslash ogni volta che usi le regexp; per questo motivo, normalmente le regexp si mettono tra apici singoli, in modo che la shell non ci metta (praticamente) mano:


matteo@teolapkubuntu:~/py/test$ echo '*'
*
matteo@teolapkubuntu:~/py/test$ echo '\*'
\*

toni00t
23-03-2014, 15:08
ciao , grazie delle risposte , finalmente ho capito i motivi dei miei errori: c'è un ultima cosa che però non mi torna

ho i seguenti file :


appppppppppj.txt
il ppppp ddsa l.txt
ppppmijhij.txt
pppppp\lk.txt
pppppppppppppppjkjk.txt


è assurdo , ma se do il comando ls | grep -E p"{3,5}" , me li restituisce tutti e 4 invece
di darmi solo i file che hanno un numero di p compreso tra 3 e 5 .perchè?
nel mio manuale , classic shell scripting o'really non ne spiega il motivo

MItaly
23-03-2014, 18:49
Perché ti stupisce? grep matcha sottostringhe che iniziano o finiscono in un punto qualunque della riga, di fatto la tua espressione richiede semplicemente che ci siano più di tre p di fila in un punto qualunque di ciascuna riga (e quindi non pone limite al numero massimo di p consecutive). Per fare quello che chiedi, dovresti usare una regex del tipo

(^|[^p])p{3,5}([^p]|$)
(a te il capire come funziona ;) )

toni00t
23-03-2014, 20:42
Perché ti stupisce? grep matcha sottostringhe che iniziano o finiscono in un punto qualunque della riga, di fatto la tua espressione richiede semplicemente che ci siano più di tre p di fila in un punto qualunque di ciascuna riga (e quindi non pone limite al numero massimo di p consecutive). Per fare quello che chiedi, dovresti usare una regex del tipo

(^|[^p])p{3,5}([^p]|$)
(a te il capire come funziona ;) )

comincia con qualsiasi carattere(non si scrive ^. ???) eccetto p
dopo un numero di p da a 5
finisci con qualsiasi carattere eccetto p

perchè tutti quegli or ??

toni00t
19-04-2014, 15:10
ciao ho trovato per caso questa soluzione :

"^([^p]*p){3,5}[^p]*$"
funziona , ma...perchè sono obbligato a specificare il gruppo all inizio?
dove hai imparato a scrivere quelle regex?

MItaly
21-04-2014, 00:01
ciao ho trovato per caso questa soluzione :

"^([^p]*p){3,5}[^p]*$"
Non mi sembra che risponda a quello che chiedi, ad esempio questa regex matcha come corretta una cosa del tipo


apapap

Per quanto riguarda la mia (sorry, mi ero perso il messaggio :stordita: ) avevo fatto un po' di confusione a mia volta :stordita: la versione corretta direi che potrebbe essere:


^[^p]*p{3,5}[^p]*$

che matcha solo stringhe che contengono da tre a cinque p incluse tra caratteri non-p.


dove hai imparato a scrivere quelle regex?
Esperienza sul campo, uso quotidiano di vim (dove l'uso delle regex è praticamente continuo :D ) e di grep.

Loading