Pagina 1 di 1
[BASH] Ricerca grep mantenendo formattazione
Inviato: venerdì 11 aprile 2014, 12:01
da Boscagoo
Salve a tutti, non riesco a trovare una soluzione ad un problema per un elaborato. Dato un file come questo:
Codice: Seleziona tutto
1:2+2
2:5*8
3:4/7
4:3*2
5:1*85
6:6*6
7:9*8
8:10*1
9:2*8
10:2*3
11:5*9
12:2*5/5
13:3*2*6
dato un pattern inserito da utente (che può essere un numero oppure una espressione aritmetica semplice come + , - , * , /), devo stampare a video il risultato, in ordine inverso di numerazione con il match del pattern. Forse non mi sono spiegato bene...provo con un esempio. Se l'utente inserisce come patter "2", il risultato del mio comando deve essere:
Se invece inserisce "+" come pattern da ricercare, il risultato deve essere:
Il comando che ho provato a scrivere è il seguente:
Codice: Seleziona tutto
sort -nr $session.log | cut -d":" -f2 | grep -n "$pattern"
cioè, inverto la selezione in ordine numerico, considero la seconda parte con il delimintatore ":" e mostro ciò che richiede l'utente.
Il mio problema è la perdita della numerazione tramite il primo cut. Ho provato a guardare sul man se tramite grep posso ricercare da un certo punto in poi senza eliminare il numero progressivo, ma senza successo. Qualcuno sa darmi qualche consiglio? Grazie
M.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: venerdì 11 aprile 2014, 18:18
da UbuNuovo
Non ho capito a che ti serve cut; o forse non ti sei spiegato bene.
Per quel che ho capito basta ribaltare la disposizione:
Codice: Seleziona tutto
8-) cat session.log
1:2+2
2:5*8
3:4/7
4:3*2
5:1*85
6:6*6
7:9*8
8:10*1
9:2*8
10:2*3
11:5*9
12:2*5/5
13:3*2*6
8-) pattern=2
8-) grep "$pattern" session.log | sort -nr
13:3*2*6
12:2*5/5
10:2*3
9:2*8
4:3*2
2:5*8
1:2+2
8-) pattern='+'
8-) grep "$pattern" session.log | sort -nr
1:2+2
8-)
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 3:26
da crap0101
secondo me è srot che non gli serve... da quel che ho capito filtrare le linee e poi stamparle in ordine inverso
Codice: Seleziona tutto
crap0101@orange:/tmp/FOO$ cut -d: -f2 < file.txt | grep 2 | tac
3*2*6
2*5/5
2*3
2*8
3*2
2+2
il cut serve perchè - presumo - la prima parte della linea
è una specie di indice e non va matchata.
L'output ovviamente sarà diverso da quello dell'esempio del primo post, appunto perchè la prima parte viene tagliata via, nel caso debba essere preservata basta togliere il cut e usare modificare il pattern di grep in modo da tenerne conto.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 10:55
da UbuNuovo
Giusto! non l'avevo proprio considerato.
Se avessi letto con più attenzione gli esempi di output mi sarei reso conto dell'errore

.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 12:15
da UbuNuovo
Riguardando l'esempio sembra però che debba mantenere il vecchio numero di riga.
In questo caso, senza usare 'grep -P' o 'awk', considerando che studia le 'pipe', potrebbe fare così:
Codice: Seleziona tutto
8-) pattern=2
8-) grep -v "^$pattern:" session.log | grep "$pattern" | tac
13:3*2*6
12:2*5/5
10:2*3
9:2*8
4:3*2
1:2+2
8-) grep -v "^$pattern:" session.log | grep "$pattern" | tac
1:2+2
o con 'sort' al posto di 'tac'
Codice: Seleziona tutto
8-) grep -v "^$pattern:" session.log | grep "$pattern" | sort -nr
13:3*2*6
12:2*5/5
10:2*3
9:2*8
4:3*2
1:2+2
edit: ripensandoci, così va bene solo per il caso specifico, qundi
non va bene
Quando ho un po di tempo provo altri metodi.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 16:01
da vaeVictis
Come suggerito da UbuNuovo, è sicuramente meglio, da un punto di vista delle performance, fare prima il grep e poi il riordinamento.
Se devi semplicemente "ribaltare" l'output, però, conviene usare tac e non sort. Anche nel caso in cui tu usi sort

A margine, per eliminare la parte fino ai due punti si può usare anche \K delle espressioni regolari in stile perl, oppure una doppia istruzione per sed.
Non mi dilungo su questo punto, però, perché a parte l'uso di un comando in meno, comporta maneggiare differentemente il "pattern" che si passa.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 16:14
da UbuNuovo
Avevo pensato anch'io a \K ma sorge il problema del passare i pattern '+' e '*'
con:
Codice: Seleziona tutto
8-) pattern=2
8-) grep -P "(^.*:)\K.*$pattern" session.log | tac
13:3*2*6
12:2*5/5
10:2*3
9:2*8
4:3*2
1:2+2
8-) pattern='\+'
8-) grep -P "(^.*:)\K.*$pattern" session.log | tac
1:2+2
questo metodo necessita dell'escape di '+' e '*'
quindi ci vorrebbe l'aggiunta del '\' che si potrebbe fare con un if:
Codice: Seleziona tutto
#!/bin/bash
echo 'Inserisci il pattern'
read pattern
if [ "$pattern" = "+" -o "$pattern" = "*" ]
then
pattern='\'"$pattern"
fi
grep -P "(^.*:)\K.*$pattern" session.log | tac
Ma bisognerebbe sapere cosa può o non può usare: array? File temp? awk? ...
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 16:24
da vaeVictis
Sì, il problema nell'uso di \K è legato alla ricerca "nuda e cruda" di caratteri che nelle espressioni regolari hanno particolari significati.
Per questo dicevo che, se la si usa, bisogna manipolare "con destrezza" le espressioni regolari.
Ovviamente l'utente che usa l'eventuale comando non può "accollarsi" l'onere, quindi andrebbe modificata con una sorta di passaggio intermedio.
Io però non farei un test con -o multipli, perché può diventare troppo lungo.
Mi farei una funzione "isIn" e vedrei se il carattere è interno ad una lista di caratteri problematici.
Il problema è che, usando le espressioni regolari di Perl, temo sia proprio sbagliato ragionare in questi termini... perché anche l'espressione regolare '2+' sarebbe interpretata in modo diverso da quello "letterale".
Pertanto... o si lascia l'onere dell'uso della corretta espressione regolare all'utente... o si spera che esista un "traduttore" di espressioni regolari... ma al momento non mi pare di ricordarmi niente in questo senso.
Se proprio non si vuole usare il cat, credo sia meglio usare sed.
Ma non so quanto sia appropriato parlarne in questa discussione (intendo per le finalità di chi l'ha aperta).
Era solo per dire

Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 16:33
da UbuNuovo
Ora sto facendo altro ma credo che ci sia un metodo che faccia uso di comandi semplici (semmai poco efficienti) e che ora non ci viene in mente.
Altrimenti l'esercizio non mi sembrerebbe adeguato solo all'uso di pipe.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: sabato 12 aprile 2014, 17:48
da UbuNuovo
Non dovrei pensarci ma mi è rimasto in capo questo argomento... mi è venuto in mente al volo questo:
Codice: Seleziona tutto
#!/bin/bash
echo 'Inserisci il pattern'
read pattern
risultati=''
while read linea
do
indice=$(cut -d: -f1 <(echo "$linea"))
riga=$(cut -d: -f2 <(echo "$linea"))
if grep -Fq "$pattern" <(echo "$riga")
then
risultati+="$indice:$riga\n"
fi
done < session.log
tac <(echo -e "$risultati")
Macchinosa ma di semplice comprensione
edit: Oops, mi ero dimenticato che devi usare le pipe
Codice: Seleziona tutto
#!/bin/bash
echo 'Inserisci il pattern'
read pattern
risultati=''
while read linea
do
indice=$(echo "$linea" | cut -d: -f1)
riga=$(echo "$linea" | cut -d: -f2)
if echo "$riga" | grep -Fq "$pattern"
then
risultati+="$indice:$riga\n"
fi
done < session.log
echo -e "$risultati" | tac
Comunque sono da evitare!
Quando siamo givanissimi (nell'apprendimento di bash) si fa molto uso delle pipe, poi conoscendo tecniche migliori che danno risultati più soddisfacenti si cerca di abbandonale il più possibile.

Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:05
da Boscagoo
wow, quante risposte...e io sono qui a spaccarmi la testa...allora, facciamo un po' di ordine...allora, io devo mantenere la formattazione, ovvero, il mio output, se il pattern passato è "2" sarebbe quello riportato:
quindi, mantenendo il numero di riga. Attenzione però...vorrei fare notare che, se immetto "2", il risultato non deve anche contenere la linea 2! Ho provato il comando suggerito da
UbuNuovo funzionerebbe alla grande, ma come detto, se ho una riga nel file come questa:
non me la mostra. Quindi ho preso in considerazione la soluzione proposta sempre da
UbuNuovo , ovvero
ma purtroppo non posso immettere codice Perl o TLC (o come si chiama, non ricordo). So che è soltanto un parametro dato tramite bash normalmente, ma ho paura che durante la presentazione orale...lo considerino come fuori argomento dalla bash (può essere anche no! appunto perchè è solo un paramentro).
Per rispondere a
UbuNuovo , posso usare array, file di temp ecc.... ma non script esterni di TLC o Perl o altro, ed è meglio se riesco ad evitare awk e sed e comandi di trattamento output. Vi dico su cosa sta lavorando:
ma prende solo se il primo carretere dopo i : è pattern
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:17
da vaeVictis
Il carattere ^ dovresti metterlo prima della parentesi quadra di apertura
Inoltre prima dell'asterisco devi mettere il .
Relativamente all'inserimento di "codice Perl", quello che dovresti inserire non è "codice Perl", ma un'espressione regolare (analoga a quella che stai già usando) ma nella sintassi accettata da Perl
p.s.:
Visti i tentativi un po' alla cieca di utilizzare le espressioni regolari sorge spontanea una domanda... dove le stai studiando?
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:22
da Boscagoo
sisi, immagino....ma: aggiornamento: ecco qui
ma se ricerco con pattern "2+" esplode....dovrei fare in modo che, quando c'è uno dei simboli elementari "+" "-" "*" "/" di mettere il carattere di escape "/" davanti..
M.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:24
da vaeVictis
Al momento non ho modo di mettermi a controllare l'espressione regolare.
Ti lascio solo con un consiglio.
L'uso del comando egrep è deprecato.
Si usa il comando grep con l'opzione -E
Inoltre, il carattere di escape è \
E i problemi sono relativi a caratteri che in realtà assumono un "significato" particolare nelle espressioni regolari (in questo caso sono più che altro quantificatori).
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:28
da UbuNuovo
Ti rispondo al volo perché ho da fare altro.
Hai provato lo script con il ciclo while? Non fa uso di comandi esterni o evoluti e mi pare che faccia quello che chiedevi: cerca il pattern solo dopo i due punti mantenendo però l'intera riga in output.
Usa le classiche opzioni di grep: '-q' per non mostrare l'output e '-F' per considerare il pattern letteralmente, quindi puoi inserire '+' o '*' (senza escape), senza che questi vengano espansi. Problema che avresti anche con 'grep -E'.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:35
da Boscagoo
Chiedo venia, si, il carattere di escape è \ (sto continuando a switchare dalla tastiera italiana a quella americana). si, concordo che egrep è deprecato, ho visto sempre usare solo grep a dire il vero....è anche vero perchè che ci è stato spiegato, quindi lo uso

Con grep -e , la sintassi rimane invariata? adesso controllo...anche perchè stavo valutanto di utilizzare il comando tr, in modo da sostituire * con \* e darlo in pasto alla variabile pattern...potrebbe essere una buona idea?
Il ciclo while lo provo....perchè chiedono qualcosa di molto compatto, risolvibile in particolar modo con comandi in pipe.
M.
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:45
da vaeVictis
Con tr dovresti fare una singola conversione (una pipe) per ogni carattere cui vuoi far precedere lo slash.
Conviene usare sed... anche se sto ancora cercando (nel poco tempo che mi avanza) un programma che magari semplifichi la cosa, ma non lo trovo

Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: lunedì 14 aprile 2014, 16:48
da UbuNuovo
grep -E la 'e' è maiuscola, la sintassi è invariata.
Se fai una funzioncina per "escapare i caratteri problematici" lo script si allunga ugualmente.
Se levi la parte del read che ho messo per comodità per fare le prove, lo script è abbastanza ridotto, e funziona in base ai 'pipe' (vedi la seconda scrittura dello stesso codice)
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: mercoledì 16 aprile 2014, 11:42
da Boscagoo
Codice: Seleziona tutto
cut -d":" -f2 "$session.log" | fgrep -n "$pattern" | sort -r -V
Eccolo qui....con il cut prendo la seconda parte dopo i : messi come separatore, poi con il fgrep cerco il pattern e con il paramentro -n faccio un listato che non viene controllato dalla ricerca del grep e infine rovescio il risutalto...che stupidata!
Re: [BASH] Ricerca grep mantenendo formattazione
Inviato: mercoledì 16 aprile 2014, 11:58
da UbuNuovo
Davvero!
Bravo, non ricordavo che 'grep -n' utilizzasse i numeri di riga del file di input, pensavo che contasse Le righe in input....
buon per me!
Comunque è meglio se usi 'grep -F' al posto di 'fgrep' e 'tac' al posto di sort.