Newsgroup: it.comp.os.linux.iniziare
Titolo: script che "aggiorna" un file

Salve a tutti
ho un file di testo dove ho tutto uno storico di informazioni.
In testa a questo file di testo c'è la data di ultima modifica, seguita da
una sequenza di righe con le mie informazioni.
Queste informazioni non le scrivo io, ma sono generate automaticamente da un
sito web: scaricandole ho un altro file di testo, dello stesso formato
(data ultima modifica + una specie di csv), più aggiornato di quello mio ma
con informazioni fino agli ultimi 3/4 mesi (mentre il mio è uno storico di
un anno e passa).
vorrei, quindi, poter "inserire" automaticamente la data di ultima modifica
e le nuove informazioni nel mio file.
Stavo provando a giocare con diff e patch, ma, ora come ora, non vedo come
poter dire a nessuno dei due "dimmi solo le righe modificate e aggiunte,
non mi dire le cancellazioni".
Avevo in testa di usare sed o awk per filtrare le righe di cancellazione, ma
non è così banale, visto che devo togliere anche le indicazioni del numero
riga a cui applicare la modifica (nel formato unificato di diff, quelle che
iniziano per @@) perché comunque dovrei comunque lasciare un file da dare
in pasto a patch che "funzioni"
Sapete darmi qualche indicazione? (alla peggio penso di potermi fare uno
script da zero in python, ma preferirei usare programmi già fatti)
-- 
By ZeD

 
puoi fare un esempio?
non capito bene cosa vuoi fare

 non capito bene cosa vuoi fare
ho un mio file, chiamamolo A, del tipo
$ cat A
ultima modifica: 10/01/2009
a1,a2,a3,a4
b1,b2,b3,b4
c1,c2,c3,c4
$
e ho un'altro file, B, con lo stesso formato
$ cat B
ultima modifica: 02/02/2009
x1,x2,x3,x4
a1,a2,a3,a4
b1,b2,b3,b4
$
come vedi B è "più nuovo" di A (nel senso che la data di ultima modifica è
da aggiornare).
Inoltre c'è una riga nuova (quella con x1...)
Purtroppo, però, il sito web da cui ho B mostra solo un sottoinsieme delle
righe: infatti in B non c'è l'ultima riga di A (quella con c1...).
Quello che vorrei è modificare A (per ora mi accontento di creare un nuovo
file C) che unisca ad A le "novità" introdotte da B
$ cat C
ultima modifica: 02/02/2009
x1,x2,x3,x4
a1,a2,a3,a4
b1,b2,b3,b4
c1,c2,c3,c4
$
anche se nel frattempo sto già risolvendo con uno scriptone in python,
preferirei sostituirlo con qualche cosa di già fatto
-- 
By ZeD



Non hai specificato se C deve contenere le righe di A + quelle nuove di B in
qualunque ordine oppure in un ben preciso ordine. Dall'esempio che fai,
sembrerebbe che le righe nuove di B debbano essere inserite in cima. Non
hai nemmeno detto se si puo' supporre a priori che tu sappia quale file e'
il piu' nuovo oppure se deve essere il programma a determinarlo leggendo la
prima riga di ogni file. Poi, nel tuo primo  messaggio parli di "righe
modificate e aggiunte": come discrimini una riga che e' nuova da una che e'
una modificazione di una esistente?
Con queste informazioni dovrebbe essere possibile scrivere qualcosa in awk.

 awk.
mah, non conosco così bene awk, ma non sembra possa essere applicato su 2
stream contemporaneamente (o tu intendevi diff + awk + patch?)
-- 
By ZeD


le righe presenti in a ma non in b:
diff a b|grep "<"|grep -v ultima|cut -d " " -f 2
il risultato di questo puoi direttamente appenderlo a b con un  >>b
resta da fare la parte per la riga iniziale, il confronto tra date in bash
non è che sia il massimo, potresti farlo con "date", certo che averle
memorizzate in un altro formato nel file sarebbe meglio (vedi: YYYY-MM-GG)
oppure , se la data di modifica del file corrispondesse anche alla data Di
"ultima modifica" contenuta al suo interno:
diff `ls -t a b`|grep ">"|grep -v ultima|cut -d " " -f 2 >> `ls -t1 a b
|head -n 1`

 |head -n 1`
ho scritto a braccio e forse ho sbagliato, in uno di quei due ls ci va una
r, probabilmente.
Verifica tu in quale :)

 stream contemporaneamente (o tu intendevi diff + awk + patch?)
Importante: tutte le soluzioni presuppongono che non ci siano linee
duplicate nello stesso file.
Si puo' fare con una combinazione di comandi. Ad esempio
(head -n 1 B
 grep -vxF -f <(tail -n +2 A) <(tail -n +2 B)
 tail -n +2 A) > C
(assumendo che B sia il file piu' nuovo)
Il problema di questo approccio e' che grep deve fare una sottrazione tra
due file, operazione che potrebbe potenzialmente essere poco efficiente
(ordine n^2, anche se probabilmente grep fa qualche ottimizzazione perche'
generalmente e' abbastanza veloce).
La soluzione per ottenere la sottrazione tra i due file usando awk e' una
cosa del tipo (la prima e la terza riga sono uguali a prima)
(head -n 1 B
 awk 'NR==FNR{a[$0];next} !($0 in a)' <(tail -n +2 A) <(tail -n +2 B)
 tail -n +2 A) > C
che e' piu' efficiente perche' usa gli hash, ma in compenso deve leggersi in
memoria tutto il file A.
Si potrebbe anche fare tutto in awk, ma diventa un po' meno elegante
(ammesso che come e' ora lo sia:)).
Vedi 
http://wooledge.org:8000/BashFAQ/036
 per maggiori info su questo tipo
di operazioni sui file.