Newsgroup: it.comp.os.linux.iniziare
Titolo: eliminazione righe da un file

Ho un file con qualche decina di migliaia di righe
In una lista ho qualche centanaio o più, di numeri
Ho bisogno di eliminare le righe nel primo file corrispondenti alle
righe nella lista.
Come si può fare senza avere tempi non eccessivamente elevati?
Matteo


Cioè hai un file da filtrare e in un secondo file hai la lista delle 
voci da bloccare.
grep è quello che fa per te.
dal manuale di grep:
-v, --invert-match
    Invert the sense of matching, to select non-matching lines.
-f FILE, --file=FILE
    Obtain patterns from FILE, one per line.  The empty file contains 
zero patterns, and therefore matches nothing.
Rendiamo graze al grep :-)
quindi potresti scrivere
grep -v -f lista filegrosso > filefiltrato
sul mio pc, partendo da un file di 239136 righe, una lista di 5 
elementi, impiega circa 17 secondi.
con una lista di 10 elementi il tempo sale a 29 secondi. (poco meno del 
doppio).
Ah, ho un Athlon 2400+ (certamente su un P2 i tempi aumenterebbero :-) )
LP

 righe nella lista.
Le righe ce l'ha un file, allora 'sta lista è un file?
in ogni caso, ti consiglio di usare uno script python
crei lista numeri 
leggi dal file1 una riga alla volta
se il numero di riga sta nella lista => salva la riga in un file2
alla fine : 
unlink file1
rename file2 in file1
ciao


diff
man diff
-- 
    Uranium per Capsule Corp. con Debian
==============================================
"Bene, ho finito di tagliar la legna! Nd Goku"
==============================================
    Pubblic key = 
http://snipurl.com/16uib


Scusate tutti se non ho più risposto.
Alla fine non mi è più servito (visto che quello che dovevo fare
riguardava 10 righe invece di 10000 :-).
cmq spiego meglio la situazione
ho un file 'pippo':
a
b
c
d
e
f
g
h
per lista di numeri intendo un insieme, una serie di numeri
memorizzabili a scelta o in un file o in una variabile.
caso 2:
Y="2 5 7"
l'output deve essere il file senza la seconda, quinta e settima riga.
quindi:
a
c
d
f
h
La procedura di RedWiz è la prima che mi è venuta in mente, però non
voglio usare linguaggi di programmazione.
Utilizzando bash viene fuori
$ cat pippo |while read a;do
      echo $X|grep -wq $Y || echo "$a"
      Y=$[$Y+1]
done
ma non si può dire che sia una scheggia su molte righe.
la stessa procedura nel caso la serie sta in un file
file numeri:
2
5
7
$ cat pippo |while read a;do
      grep -wq $Y numeri || echo "$a"
      Y=$[$Y+1]
done
---
Rendendo lode a grep, utilizzando i file di cui sopra senza
manipolazioni non ottengo nulla di buono. Tuttavia mi sono appena
accorto che funziona e ottengo la soluzione più performante con:
$ cat pippo |grep -n ^|grep -vw -f numeri |cut -f2- -d:
ma questo vale solamente se in pippo non ci sono numeri (o almeno
quelli presenti nel secondo file)
l'idea è:
aggiungi il numero di riga all'inizio di ogni diga con grep -n (1:a
2:b 3:c ...)
confronto con grep -f e poi elimino i file aggiunti all'inizio con cut
vale per file con numeri aggiungendo un ^ all'inizio di ogni riga in
'numeri'
$ sed -i -e 's/^/^/' numeri
con diff la vedo veramente complicata.
Alla fine ho utilizzato un mostro di accozzaglia (non avevo ancora
pensato alle soluzioni di cui sopra), scritto in fretta. Qualcosa
tipo:
aggiungi i numeri di riga con grep -1
unisci i due file (cat pippo numeri |sort -n >pippo1)
Matteo
con uniq escludi le righe duplicate (confrontando solamente la prima
colonna)
togli i numeri di riga

$ sed -i -e 's/^/^/' numeri
Scusa eh ma guarda questo comando (poi magari ci fai lo
script per le altre 10.000 righe:
cat pippo | sed 2,5,7d >pippo.new
(ma bada che mica ci devi mettere i numeri-etichetta eh)
-- 
Saluti, Dalet


Buono. non conosco tutte le potenzialità di sed (finora l'ho
utilizzato solo per le regexp) però c'è qualcosa che non funziona:
# cat pippo |sed 2,5,7d
sed: -e expression #1, char 4: unknown command: `,'
# cat pippo |sed 2,5d
a
f
g
h
In pratica mi sembra che voglia 2 parametri e che questi debbano
indicare un intervallo.
Matteo

indicare un intervallo.
Eh si' non c'avevo badato, c'ha due soli indirizzi.
Non solo, ma se metti 1,5d ti cancella anche le righe 2 3 4
comprese tra 1 e 5.
Non va proprio, mi spiace.
-- 
Saluti, Dalet

 
1) sed 2,5d ... cancella le righe dalla due alla cinque
   ossia cancella le righe due, tre, quattro e cinque.
2) sed 5,7 ... cancella le righe dalla cinque alla sette
   ossia cancella le righe cinque, sei e sette.
3) sed 2d;5d;7d; ... cancella le righe due, cinque e sette.
4) sed 2,5,7d ... e` un errore di sintassi.
5) cosa non va in:
     sed 2d;5d;7d; pippo > pippo.new 
   ?
 

 sed 2d;5d;7d; ...
Intendi:
sed '2d;5d;7d;' ...
sed "2d;5d;7d;" ...
sed 2d\;5d\;7d\; ...
et cetera.
Scusate effetto della fame :(

sed 2d\;5d\;7d\; ...
Bellissimo!  ma come diavolo hai fatto a trovarlo?
Non mi sembra che sia documentata come sintassi.
Va indifferentemente in tutti e tre i modi, ma e' proprio
indifferente?
Inoltre si puo' ovviamente combinare:
'2,4d;7d' --> 2 3 4 7
[l'ultimo ; non sembra invece servire]
-- 
Saluti, Dalet

 [l'ultimo ; non sembra invece servire]
In effetti...
 

info sed
A questo non ci avevo proprio pensato, ce ne son tanto
poche! TNX
-- 
Saluti, Dalet


Perfetto. Funziona.
Per completezza ecco come visualizzare solo 10 righe a caso in un file
(può tornare utile)
$ cat pippo |sed -n "$(for x in `seq 1 10`;do echo -n $[`cat pippo|wc -
l`*$RANDOM/100000]p\;;done)"
Grazie,
Matteo