[risolto]espressioni regolari, ottenere una parte di stringa

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

[risolto]espressioni regolari, ottenere una parte di stringa

Messaggio da melfnt »

Salve a tutti, per il programma che sto scrivendo ora in bash ho una serie di espressioni regolari e delle stringhe da controllare.
Ogni espressione regolare è formata da una parte "fissa" (in minuscolo) e una parte "variabile" (in MAIUSCOLO), per esempio in

Codice: Seleziona tutto

/usr/local/share/DIR/*
/usr/share e * compongono la parte fissa
DIR è la parte variabile

Per ogni stringa, devo stabilire se matcha una delle espressioni regolari, e in tal caso ottenere la parte variabile.
Ad esempio, la stringa "/usr/local/share/misqui/texture/dr.bmp" matcha l'espressione regolare di prima, quindi devo salvare in una variabile la parola "misqui" (corrispondente a DIR dell'espressione regolare).

Il matching è facile, forse ci riesco anche da solo:

Codice: Seleziona tutto

grep /usr/local/share/*
o qualcosa del genere.

Il problema è l'estrapolazione della parte variabile che non so come si faccia.
Mi potreste dare una mano?

Vi posto altri esempi di pattern commentati:

Codice: Seleziona tutto

/usr/local/include/FILE
Devo ottenere FILE

Codice: Seleziona tutto

/usr/local/include/DIR/*
devo ottenere DIR, non importa cosa ci sia al posto dell'asterisco

Codice: Seleziona tutto

/usr/local/share/applications/FILE.desktop
Devo ottenere FILE, ma mi va bene anche "FILE.desktop" perché il ".desktop" finale lo so togliere

Codice: Seleziona tutto

/usr/local/share/man/man[1..8]/FILE
 
Devo ottenere FILE, non importa quale numero ci sia dentro le quadre.
Per esempio, in /usr/local/share/man/man1/ciao FILE=ciao
/usr/local/share/man/man4/arrivederci FILE=arrivederci
/usr/local/share/man/man9/ciao non matcha
e così via

Grazie in anticipo per le risposte.
Per ora va bene anche una cascata di "if" differente per ogni espressione regolare, poi vedrò se c'è verso eseguire per tutte le stesse istruzioni.
;)
Ultima modifica di melfnt il domenica 29 giugno 2014, 12:46, modificato 1 volta in totale.
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da UbuNuovo »

Stai facendo uso del globbing più che delle espressioni regolari, ma per quello che ho capito può bastare.
Al posto di grep, in questo caso, 'grep /usr/local/share/*' è adatto "ls":

Codice: Seleziona tutto

ls /usr/local/share/*

Codice: Seleziona tutto

/usr/local/include/FILE 	# stesso discorso puoi usare ls /percorso/*

/usr/local/share/applications/FILE.desktop  # idem

/usr/local/share/man/man[1..8]/FILE

ls /usr/local/share/man/man*/*
Forse non ho capito bene quello che vuoi ottenere...
Per fare ricerche per directory o per file o per una data profondità di ricerca puoi usare find
-type d # elenca le directory
-type f # elenca i file
-maxdepth N e mindepth N # N=numero intero, indicano la profondità massima e minima della ricerca

Per cercare file che rispettano una data sintassi si possono usare le espressioni regolari: direttamente con find o filtrandone i risultati con grep.
Semmai cerca di spiegare più in dettaglio qual'è il problema.
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da melfnt »

No, il fatto che le espressioni regolari siano percorsi di file non c'entra niente, o comunque non c'entrano niente i file esistenti nel mio filesystem, che verrebbero elencati con `ls`.

Faccio un altro esempio: data l'espressione regolare "nel mezzo del XXX di nostra *", devo stabilire se una stringa la matcha, e in tal caso estrapolare XXX da quella stringa:
"nel mezzo del cammin di nostra vita" -> XXX=cammin
"nel mezzo del corso di nostra città" -> XXX=corso
"nel mezzo busto di nostra madre" non matcha (manca "del")

Come vedi il problema non è strettamente legato ai file, e non posso risolverlo con comandi del tipo `ls` o `find`, anche perché mi interessano solo alcuni file e non tutti quelli che matcherebbero l'espressione regolare.

A questo punto ripropongo il problema in una forma equivalente ma più comprensibile:
Ho due espressioni regolari: $prima e $dopo, e una serie di stringhe.

Per ogni stringa S, devo fare due cose:
1- stabilire se S matcha "$prima*$dopo", e questo lo so fare
2- se sì, estrapolare la stringa che nel punto precedente sta al posto dell'asterisco.

Esempi:
$prima="/usr/share/"
$dopo="/*"
S1="/usr/share/misqui/texture/dr.bmp"
S2="/usr/share/s/"
S3="/usr/share/ciao"
S4="/usr/local/share/applications/dd"

risultato:
S1 matcha, e la stringa estrapolata è "misqui".
S2 matcha, e la stringa estrapolata è "s".
S3 ed S4 non matchano.

Ciò che manca a me è il comando per prendere dalla stringa solo ciò che è compreso fra $prima e $dopo, usando sed, grep, awk e cose simili e senza fare assunzioni sui file presenti nel file system.

Spero di essermi spiegato ora.
;)
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da vaeVictis »

Guarda che, come ti diceva UbuNuovo, non stai affatto usando le espressioni regolari ma il globbing.
Nelle espressioni regolari l'asterisco è un quantificatore, che indica la ripetizione (0 o più occorrenze) del carattere che la precede.

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~$ echo "f" | grep -E "fo*"
f
vaevictis@vaevictis-HAL:~$ echo "fo" | grep -E "fo*"
fo
vaevictis@vaevictis-HAL:~$ echo "fooooooooooooooooooooooooooo" | grep -E "fo*"
fooooooooooooooooooooooooooo

Codice: Seleziona tutto

Come vedi il problema non è strettamente legato ai file, e non posso risolverlo con comandi del tipo `ls` o `find`, anche perché mi interessano solo alcuni file e non tutti quelli che matcherebbero l'espressione regolare.
Ni.
Nel senso che di sicuro in qualche modo tu ottieni la lista di questi file.
E già usando per bene find puoi fare una bella scrematura di quello che poi vai a "matchare".

Non sei il massimo della chiarezza, ma se ho capito più o meno quello che intendi fare

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~$ echo "prima_freghete_dopo" | sed 's/prima\(.*\)dopo/\1/'
_freghete_
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da UbuNuovo »

Mi sento ancora rimbecillito ma forse:

Codice: Seleziona tutto

8-) path="/usr/share/misqui/texture/dr.bmp"
8-) grep -oP '/usr/share/\K(.*?)(?=/texture/dr.bmp)' <(echo "$path")
misqui
edit:
Vae anch'io l'ho intesa in quel modo, quindi si può usare sia sed che grep -P, volendo si possono inserire le variabili giocando con le virgolette.
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da melfnt »

No, esatto: non sono il massimo della chiarezza.

Davo per scontato era che * significhi "una qualsiasi sequenza di zero o più caratteri".
Un'altra cosa che forse non ho spiegato bene è che i file nel mio filesystem non c'entrano nulla con l'esecuzione del programma.

Il fatto di aver portato sempre esempi che riguardano file è stato fuorviante.
Mi spiego meglio con un pezzo di codice:

Codice: Seleziona tutto

prima="prima"
dopo="dopo"
for S in ${stringhe[*]}
do
 #codice magico che ancora non conosco
done
Che dovrebbe essere più o meno come funzionerà il mio programma.
Come vedete, i file non c'entrano niente ($stringhe, $prima e $dopo possono assumere valori arbitrari)

Il codice di vaeVictis è quello che cerco, nella forma

Codice: Seleziona tutto

sed 's/$prima\(.*\)$dopo/\1/'
dove $prima e $dopo sono espressioni regolari nelle quali l'asterisco indica una sequenza di zero o più caratteri.
C'è verso di fare una cosa del genere?
;)

edit: va bene anche quello di UbuNuovo, con la possibilità di inserire espressioni regolari al posto della stringa fissa prima e dopo.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da vaeVictis »

Per entrambi i comandi puoi inserire delle espressioni regolari mettendo nel modo opportuno gli "apici".
Ci sono pacchi di discussioni a riguardo :)
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da UbuNuovo »

Per esempio inserendo delle variabili:

Codice: Seleziona tutto

path="/usr/share/misqui/texture/dr.bmp"
prima='/usr/share/'
dopo='/texture/dr.bmp'
match=$( grep -oP "$prima\K(.*?)(?=$dopo)" <(echo "$path") )
echo "$match"
Al posto delle stringhe in prima e dopo puoi inserire quello che vuoi anche RE ma io non ho ancora capito.
Ciao
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da melfnt »

Ok, così funziona!

Codice: Seleziona tutto

$ path="/usr/share/misqui/texture/dr.bmp" 
$ prima="/usr/share/"
$ dopo="/.*"
$ match=$( grep -oP "$prima\K(.*?)(?=$dopo)" <(echo "$path") )
$ echo $match
misqui
A questo punto mi sorge un dubbio: nella stringa "/usr/share/misqui/texture/dr.bmp" in realtà ci sono due modi di matchare l'espressione regolare:
/usr/share/misqui/texture/dr.bmp
/usr/share/misqui/texture/dr.bmp

In entrambe prima="/usr/share/ e dopo="/*"
A me va bene che venga preso solo "misqui", quindi non mi lamento, però posso stare sicuro che ciò accadrà per ogni stringa e per ogni espressione regolare?
Ovvero che dentro $match venga salvata sempre la stringa più corta che soddisfa l'espressione regolare?

;)
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da UbuNuovo »

Si dovrest stare tranquillo c'è "?" che rende ".*" ungready;

edit: relativamete tranquillo, essendo '.*' una RE il più generica possibile, se c'è qualche caratteristica comune nelle stringhe che cerchi dovresti inserirla.
Ultima modifica di UbuNuovo il domenica 29 giugno 2014, 12:46, modificato 1 volta in totale.
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: espressioni regolari e ottenere una parte di stringa

Messaggio da melfnt »

ok, marco come risolto e quando ho finito di scrivere il codice lo posto qui.

Grazie infinite!
;)
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

Ho fatto ora un'aggiunta al post precedente.
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da melfnt »

se c'è qualche caratteristica comune nelle stringhe che cerchi dovresti inserirla
Che significa?
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

Aspetta

Codice: Seleziona tutto

dopo="/*"
non va bene, vuol dire "/" seguita da un numero qualsiasi di "/" dovresti usare

Codice: Seleziona tutto

dopo='/.*'
Salva l'Ucraina! 🇺🇦
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

melfnt [url=http://forum.ubuntu-it.org/viewtopic.php?p=4607709#p4607709][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:
se c'è qualche caratteristica comune nelle stringhe che cerchi dovresti inserirla
Che significa?
Che si può rendere l'espressione più restrittiva ma si deve sapere almeno qualche caratteristica che accomuna le stringhe che si vanno cercando.
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da melfnt »

UbuNuovo [url=http://forum.ubuntu-it.org/viewtopic.php?p=4607710#p4607710][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Aspetta

Codice: Seleziona tutto

dopo="/*"
non va bene, vuol dire "/" seguita da un numero qualsiasi di "/" dovresti usare

Codice: Seleziona tutto

dopo='/.*'
Infatti, l'ho scritto.
Che si può rendere l'espressione più restrittiva ma si deve sapere almeno qualche caratteristica che accomuna le stringhe che si vanno cercando.
D'accordo, e dov'è che vanno scritte questa caratteristiche? al posto di .* nell'espressione regolare in stile perl?
Com'è che faccio ad indicare "una qualsiasi sequenza di caratteri che non contiene /"?
Che alla fine è quello che mi serve per essere sicuro che prenda solo il nome della cartella.
;)
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

in questo caso non ti serve in quanto i delimitatori in "prima" e "dopo" sono "/" ed essendo la RE ungready prende la parte più corta.
Non sapendo con quali stringhe reali devi lavorare ho detto che si potrebbe rendere più restrittiva la RE, ma nel 99% dei casi dovrebbe andare bene. cmunque per escludere la lettera "a" si usa [^a]
Salva l'Ucraina! 🇺🇦
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

Abbi pazienza ho detto una bischerata, non sono proprio in palla.
Dopo mangiato riguardo la situazione
Salva l'Ucraina! 🇺🇦
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da UbuNuovo »

Mentre la pasta cuoce...
se vuoi che finisca con "$dopo" ma possa contenere qualsiai cosa dopo la parte cercata e prima di "$dopo":

Codice: Seleziona tutto

8-) path="/usr/share/misqui/pio/texture/dr.bmp"
8-) prima='/usr/share/'
8-) dopo='.*/texture/dr.bmp'
8-) match=$( grep -oP "$prima\K(.*?)(?=/)(?=$dopo)" <(echo "$path") )
8-) echo "$match"
misqui
8-)
oppure inserisci ".*" nella riga di codice

Codice: Seleziona tutto

8-) path="/usr/share/misqui/pio/texture/dr.bmp"
8-) prima='/usr/share/'
8-) dopo='/texture/dr.bmp'
8-) match=$( grep -oP "$prima\K(.*?)(?=/)(?=.*$dopo)" <(echo "$path") )
8-) echo "$match"
misqui
8-) 
Salva l'Ucraina! 🇺🇦
melfnt
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1312
Iscrizione: sabato 15 ottobre 2011, 22:25

Re: [risolto]espressioni regolari, ottenere una parte di str

Messaggio da melfnt »

Il problema non è il poter contenere qualsiasi cosa prima di dopo.
Il problema è la composizione di dopo.

In questo caso, infatti, dopo contiene un *

Codice: Seleziona tutto

prima=/use/share
dopo=/.*
Come vengono espansi i due asterischi?
O meglio: come faccio a stabilire quale parte della stringa viene salvata in match e quale invece è parte di dopo?
C'è un modo per far sì che la parte matchata sia la più corta possibile, nel caso in cui ci siano più modi di matchare la RE?

Domani con calma ti posto un po' di stringhe sulle quali devo lavorare.
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 3 ospiti