Newsgroup: it.comp.os.linux.sys
Titolo: Una domanda tosta... :-)

Immaginate di avere un file di testo molto lungo. In questo file ogni tanto
si presentrano un gruppo di 20 righe che "insieme" si ripetono per un po' di
volte.
Per fare un esempio calzante, fate finta di avere il testo di una canzone,
con un ritornello che si ripresenta per esempio tre volte all'interno del
teso.
Se io volessi toglere questo ritornello con sed come dovrei fare? Non voglio
eliminare le righe singolarmente, voglio togliere tutto il ritornello quando
si presenta in tutte le sue righe. Sono stato chiaro?!
Vediamo un po' cosa ci esce ;-)
Ciao.
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.501 / Virus Database: 299 - Release Date: 14/07/2003

> Se io volessi toglere questo ritornello con sed come dovrei fare? Non
voglio
Con sed non so, ma con awk/shell si puň fare ... sono sempre 20 righe e
sempre le stesse? La prima riga si ripete *SOLO* all'inizio di quel gruppo?
D.
--------------------------------
Inviato via 
http://usenet.libero.it

La prima riga si ripete *SOLO* all'inizio di quel gruppo?
Il problema è proprio qui, ho bisogno di eliminare quel gruppo solo quando
tutte le righe sono insieme!
La prima riga la potrei trovare anche altrove (come anche le altre)
Praticamente ho bisogno di una "chiave di ricerca" multipla dove gli
elementi sono le righe del "ritornello"
Ciao!


 Vediamo un po' cosa ci esce ;-)
cat file | egrep -v ritornello
anche se il ritornello va a capo funziona lo stesso.
--
Massimiliano

 cat file | egrep -v ritornello
correggiamo ... ritornello deve essere chiuso tra doppi apici.
--
Massimiliano.

 correggiamo ... ritornello deve essere chiuso tra doppi apici.
Accipicchia, ma perchè non ci ho pensato prima :-(
Grazie 1000


 correggiamo ... ritornello deve essere chiuso tra doppi apici.
Uhm, grep 2.4.2 non funziona proprio correttamente,
infatti elimina anche solo una singola occorenza.
Esempio:
grep -v "pippo
pluto"
elimina si, "pippo\npluto", ma anche "pippo" oppure
"pluto" da soli...
Bug? Feature?
Devo provare a casa...
bye,
-- 
   Piergiorgio Sartor

 Devo provare a casa...
Prova "grep -F" ... o fgrep ;) .. non l'ho provato ma dalla man page
sembra la soluzione al problema.
--
Massimiliano.

 correggiamo ... ritornello deve essere chiuso tra doppi apici.
che figata .... non l'avrei mai detto ! :)


 sembra la soluzione al problema.
Idem, mi taglia "pippo", oppure "pluto"
od entrambi (ovviamente).
bye,
-- 
   Piergiorgio Sartor

 che figata .... non l'avrei mai detto ! :) D.
eh si: per stavolta alla faccia di AWK e Perl ;)
--
Massimiliano.



porca miseria.
... allora si ricomincia :)

 "pluto" da soli...
Mannaggia è vero!!!
Torniamo sui nostri passi, come metter su uno scriptino con awk???
Ciao!


 Ciao!
Uhmmm effettivamente non è banale .... o fai una serie di match riga per
riga all'interno di un ciclo ma mi fa schifo come soluzione .... oppure ...
metti "il ritornello" in un file di testo e appena incontri la prima riga
del ritornello fai un grep -A 20 verso un temp file e fai un diff dei due
risultati, se sono uguali allora cancelli le 20 righe. potrebbe andare ...
(non ho a disposizione una macchina per provare, sorry)
Dave


 Torniamo sui nostri passi, come metter su uno scriptino con awk???
Qualcosa tipo:
gawk '/^inizio ritornello/{for(i=1;i<20;i++) getline}{print}'
Magari funziona anche...
bye,
-- 
   Piergiorgio Sartor


il problema è che quella riga potrebbe *NON* essere l'inizio del ritornello
ma una riga 'normale' ..... per quello dicevo di fare dei match ricorsivi
... ma l'idea non me gusta...
D.


 ... ma l'idea non me gusta...
Allora avrei un'altra idea... Peggiore:
cat file|tr '\n' 'X'|sed 'd/rit1Xrit2X.../'|tr 'X' '\n'
Ovviamente "X" non deve esistere nel file...
Il problema e` che il '\n' e` sempre un po'
speciale, non saprei di sicuro come evitare
una serie di match separati.
bye,
-- 
   Piergiorgio Sartor

 Ciao!
Domanda, tra le strofe della canzone c'e' una linea vuota?
Se si, si puo' utilizzare awk come editor multilinea, ponendo l'a capo come 
separatore di campo e la linea vuota come separatore di linea. In questo 
modo il ritornello puo' essere confrontato con qualsiasi strofa come se 
fosse un confronto tra due linee.
Troppo facile? :-)


avevo pensato anch'io a trasformare tutto in una stringa e fare un match,
poi ritrasformare il tutto in un testo normale ma ci sono vari inconvenienti
.... intanto la lunghezza del testo e il numero delle righe ... mah .....


Eh eh... vi ho dato una bella gatta da pelare!!!
Io per il momento ho risolto scrivendo un piccolo programmino in c che si
passa tutte le righe, quanto incontra la prima inizia un ciclo che
incrementa un contatore se la riga successiva č quella che mi aspetto e
cosi' via, se la somma del contatore č 20 vuoldire che quelle righe sono il
"ritornello" da togliere, quindi le tolgo.
Perņ mi piacerebbe fare tutto da shell,  ma ahimč non sono proprio in grado.


 Vediamo un po' cosa ci esce ;-)
Questo funge, va bene lo stesso se e' in python?
lui si aspetta come primo parametro il file da modificare
come secondo il file contenente il ritornello
il ritornello viene sostituito da un ''
e il risultato viene scritto in un file con lo stesso nome di quello di 
input+'.new'
lo script e' semplice, non avrai problemi a modificarlo
byez
--------------------------
import sys
if len(sys.argv)<3:
	print 'Usage: script.py input-file ritornello-file'
	sys.exit(1)
 
print 'Input file:',sys.argv[1]
print 'Ritornello file:',sys.argv[2]
try:
	ritornello=file(sys.argv[2],'r').read()
	data=file(sys.argv[1],'r').read()
except IOError,e:
	print '\nErrore Apertura file'
	print e
import re
(Testo,Sostituzioni)=re.subn(re.escape(ritornello),'',data)
file(sys.argv[1]+'.new','w').write(Testo)
print "Effettuate",Sostituzioni,"sostituzioni"

 Se io volessi toglere questo ritornello con sed come dovrei fare? 
Con sed o non si può fare perché lavora su una riga alla volta o si
può fare con difficoltà se tra le sue istruzioni da linguaggio di
programmazione ce ne sono di utili per mantenere uno `stato' (`sono
all'interno del blocco cercato'/`non ci sono')
In ruby si può fare così:
blocco = 'uno
due
tre
'
testo = 'tre
uno
due
tre
uno
uno
tre
due
uno
due
uno
due
tre
tre
uno
'
puts testo.gsub(blocco, '')
Oppure:
File.open('/path/to/file') do |io|
    testo = io.read
    puts testo.gsub(blocco, '')
end
-- 
"We should not be looking for the tools that novices can safely use.
We should be looking to increase the skill of those novices so that
they can safely use the power tools that will get the real work
done."            (Robert Martin on the Pragmatic Programmer's mailing list)

 Se io volessi toglere questo ritornello con sed come dovrei fare?
Assumendo che il "ritornello" sia in ritornello.txt e il testo in
testo.txt, salva questo script:
$rit = `cat ritornello.txt`;
$_ = `cat testo.txt`;
s/$rit//sg;
print;
poi esegui con perl e ridirigi l'output su un file opportuno
(swappera' un po' se il file e' davvero lungo...)
-- 
Stefano

 print;
Niente male ;-)
L'ho appena provato e funziona. A dire il vero ormai ho risolto con un
programmillo in c che sembra essere più veloce (anzi dalla prova che ho
fatto... molto piu' veloce).
Comunque è una soluzione elegante.
Ciao e grazie lo stesso.


 che ho fatto... molto piu' veloce).
Sicuramente, immagino che tu abbia un buffer che accumula caratteri
finche' o il ritornello e' completo, allora riazzeri il buffer, oppure
caratter i del buffer e' diverso dal caratter i ritornello, allora
scrivi il buffer prima di riazzerarlo.
Per curiosita', se metti la riga "study;" prima di "s/$rit//sg;" nello
script, va piu' veloce?
-- 
Stefano