Newsgroup: it.comp.macintosh
Titolo: File di testo da processare e unire

Salve a tutto. Ho un problema e già una soluzione, purtroppo la
soluzione richiede tempo ed energie mentali che non dispongo, per cui
sto cercando una alternativa.
Ho un sacco di file di testo, molto piccoli, pochissimi kb. Questi sono
composti da una decina di righe molto simili tra loro, con delle parti
iniziali uguali, tipo dei log.
Io avrei bisogno di prendere uno a uno questi file, sono un migliaio e
più, estrapolare quelle righe che mi servono, e fare un unico file di
testo che contiene tutto.
Per far questo potrei prendere di nuovo in mano il C, farmi un
programmino, testarlo, debug, bestemmie, ecc.... Ma questo è senza
dubbio impossibile in questo momento.
Ci sono alternative? Una app già pronta da qualche parte?
TIA
-- 
Guru       Non coltivate i beni terreni,
               non rimarrà niente.
         Coltivate l'amore delle persone,
            vale più di qualsiasi oro. 

 testo che contiene tutto.
Se le righe nei tuoi file sono riconoscibili da un pattern, la maniera
piu' semplice e'
grep pattern file* > nuovofile
d

 grep pattern file* > nuovofile
Già, ma non è una sola riga, sono più righe per ogni file, e non
consecutive....


 consecutive....
ma hai provato?
-- 
http://emeraldion.it
Ma soprattutto, che minchia di genitori hanno lasciato
andare una ragazzina di 17 anni da sola a Capo Verde?

 consecutive....
Grep le vede comunque. Magari con awk.
Facci un esempio.
-- 
k|b|s  `echo 0000000:6b62734062676c75672e69740a|xxd -r`

 consecutive....
Questo se le righe che ti interessano non hanno a capo; supponendo che
ciascuna riga sia identificata da un dato pattern:
#!/bin/bash
grep pattern1 file* > nuovofile1
grep pattern2 file* > nuovofile2
... (qui aggiungi tante righe quanti i pattern)
cat nuovofile* > filetotale
(salva come script.sh, dagli i privilegi di esecuzione e lo lanci)
Oppure potresti fare uno script in python, con qualcosa del genere per
leggere i file:
f = open(nomefile, "r")
for riga in f.readlines():
# e fai qualcosa con la stringa "riga"...
# Oppure:
        elemriga = string.split(riga) 
# cosi' splitti i singoli elementi della riga e li metti come elementi
del vettore elemriga
# poi fai qualcosa con gli elementi di elemriga...
        ...
f.close()
Sospetto che cmq ci sia qualcosa di veloce in Perl (che non conosco)
Ciao
-- 
Riccardo Campana
pabel...@gmail.com
"Physics is like sex: sure, it may give some practical
results, but that's not why we do it"  (Richard Feynman)

 ma hai provato?
No, ho dato per scontato che "pattern" sia uno solo e non possa avere
più possibilità....
B"E"G"I"N":"V"M"S"G"
V"E"R"S"I"O"N":"1"."1"
X"-"I"R"M"C"-"S"T"A"T"U"S":"R"E"A"D"
X"-"I"R"M"C"-"B"O"X":"I"N"B"O"X"
X"-"N"O"K"-"D"T":"2"0"0"6"0"9"0"3"T"1"1"4"1"5"2"Z"
B"E"G"I"N":"V"C"A"R"D"
V"E"R"S"I"O"N":"2"."1"
N":"
T"E"L":"+"3"9"0"1"8"7"0"0"
E"N"D":"V"C"A"R"D"
B"E"G"I"N":"V"E"N"V"
B"E"G"I"N":"V"B"O"D"Y"
D"a"t"e":"3"."9"."2"0"0"6" "1"2":"4"1":"5"2"
ciao come va?
E"N"D":"V"B"O"D"Y"
E"N"D":"V"E"N"V"
E"N"D":"V"M"S"G"
Io devo prendere tutti i 'TEL' i 'Date' e quello che segue fino a 'END'
escuso....


 Facci un esempio.
B"E"G"I"N":"V"M"S"G"
V"E"R"S"I"O"N":"1"."1"
X"-"I"R"M"C"-"S"T"A"T"U"S":"R"E"A"D"
X"-"I"R"M"C"-"B"O"X":"I"N"B"O"X"
X"-"N"O"K"-"D"T":"2"0"0"6"0"9"0"3"T"1"1"4"1"5"2"Z"
B"E"G"I"N":"V"C"A"R"D"
V"E"R"S"I"O"N":"2"."1"
N":"
T"E"L":"+"3"9"0"1"8"7"0"0"
E"N"D":"V"C"A"R"D"
B"E"G"I"N":"V"E"N"V"
B"E"G"I"N":"V"B"O"D"Y"
D"a"t"e":"3"."9"."2"0"0"6" "1"2":"4"1":"5"2"
ciao come va?
E"N"D":"V"B"O"D"Y"
E"N"D":"V"E"N"V"
E"N"D":"V"M"S"G"
Se per ogni file devo prendere solo le righe di TEL Date e quello che
segue fino a END, e metterle tra due righe di "-----------" per dividere
da un file all'altro come fo??


 Sospetto che cmq ci sia qualcosa di veloce in Perl (che non conosco)
Eh, so che il Perl è ottimo per quello, ma dovrei mettermi a studiarlo,
ed è la stessa storia del C.....


 testo che contiene tutto.
iniziamo dall'unione die file
prova questo
http://homepage.mac.com/schwarz/
poi si pensa
ciao
-- 
Angelo
Taranto


da non programmatore:
fai un solo file con tutto (tipo con textwrangler o lightwaytext), fai un
cerca/sostituisci dei T"E"L"/Telefono e D"a"t"e"/Data e poi fai un secondo
cerca sostituisci di tutte le righe che iniziano con jolly"jolly"/niente
-- 
A signature was here.

 fai un solo file con tutto (tipo con textwrangler o lightwaytext)
come non detto, ricordavo male, i programmi che citavo non hanno la funzione
di merge. prova con quello citato da angelo.


 
http://homepage.mac.com/schwarz/
Che ha un "cat" di male? :-)


 da un file all'altro come fo??
cat $FILES | sed 's/\"//g' | awk '/TEL/ ;/Date:/, /END:VBODY/' | sed
's/END:VBODY/------------/g'


 ed č la stessa storia del C.....
Perl, Python, Awk, Ruby, sono tutti molto piu` adatti del C per questo
tipo di compiti (sono di livello piu` alto; Awk e Perl in particolare
hanno una specifica orientazione all'estrazione di testo da file, anche
se tutti questi sono linguaggi general purpose e anche Ruby e Python
rendono facilissimi questi compiti, al limite con semplici moduli delle
librerie standard).  L'apprendimento (considerando che ti basta un
piccolo sottoinsieme, eccetto magari per Awk che cmq e` il piu` limitato
e "mirato" dei quattro) e` pure molto piu` semplice del C (nessun
problema di puntatori, gestione memoria, ecc, ecc).
egrep e altri comandi CLI entro un piccolo script bash possono alla fine
essere analoghi a Perl &c, ma in realta`, salvo casi supersemplicissimi,
non convengono piu` di tanto.  Comunque se vai per questa strada fai
anche un "man awk", che in 250 righe ti riassume tutte le funzionalita`
di awk (che puoi integrare in uno script del genere).
Alex

 's/END:VBODY/------------/g'
Ci provo e ti faccio sapere....


 cerca sostituisci di tutte le righe che iniziano con jolly"jolly"/niente
Geniale! L'uovo di colombo, perché non ci ho pensato prima?? Caspita era
così semplice, faccio un "cat" unisco tutto e poi elimino tutte le parti
che non mi fregano, sostituendo con una riga di -.
Che pollo!
Grazie di tutto!!


 Che ha un "cat" di male? :-)
Durante la stagione degli amori piscia per tutto il filesystem.

 Ci provo e ti faccio sapere....
Funzione, fiditî. E cence doprà text*orcodiul e altri robis.


 Funzione, fiditî. E cence doprà text*orcodiul e altri robis.
mmmmm La prima prova non ha dato buoni frutti....
Dato che io sono un testone e se non capisco quello che faccio mi
incaponisco, ho cercato di capire "pezzo per pezzo" quella linea di
codice, ma non capisco esattamente come funziona. Se me la spiegi passo
passo magari poi me la posso debugare da me adattandola al mio caso....


 wrote:

ROFTL!
-- 
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?

 sed 's/END:VBODY/------------/g'
Sostituisce END:VBODY con --------------
Puoi redirigere il tutto su un file aggiungendo alla fine un 
"> file.txt" (senza le virgolette) 


 passo magari poi me la posso debugare da me adattandola al mio caso....
Allora, rivediamo la linea in questione, spezzandola alle sbarre
verticali e numerando le sottolinee per comodita` di riferimento:
[1] cat $FILES | 
[2]  sed 's/\"//g' | 
[3]  awk '/TEL/ ;/Date:/, /END:VBODY/' | 
[4]  sed 's/END:VBODY/------------/g'
La [1] "elenca" tutti i $FILES l'uno dopo l'altro passandone il
contenuto su standard output (quindi al resto della pipe).  Non e`
necessaria (basterebbe passare i $FILES a sed nella [2]) ma e` un vezzo
abbastanza comune di alcuni utenti Unix.
La [2] sostituisce tutte le virgolette doppie con nulla (leggendo dal
passo precedente e passando il risultato al passo successivo); come
scritta, e` un poco piu` complessa del necessario (non serve quel \
prima di ").  Si potrebbe sostituire con un
  tr -d '"'
ma in questo caso [1] sarebbe necessario (tr, a differenza di sed, non
accetta files come argomenti: lavora sempre da stdin a stdout) -- forse
questa lieve asimmetria di alcuni comandi Unix spiega il vezzo di usare
cat anche quando non serve, gia` menzionato.
La [4] sostituisce la stringa END:VBODY con dei trattini (in questo caso
sed serve, tr opera solo su singoli caratteri; ma non serve quella g,
che invece e` necessaria alla [2] -- perche` END:VBODY non appare piu`
volte per riga, le doppie virgolette invece si`).
La [3] e` forse la piu` interessante perche awk, come gia` avevo
accennato, e` in realta` un linguaggio general purpose ma molto mirato a
questo tipo di compiti.  Rivediamola...:
[3]  awk '/TEL/ ;/Date:/, /END:VBODY/' | 
Il ; separa due istruzioni, che si potrebbero anche dividere andando a
capo:
    /TEL/
    /Date:/, /END:VBODY/
La forma generale di un'istruzione awk e`:
    pattern { action }
Se manca la parte { action } il default e` "emettere la riga su standard
output"; se manca la pattern, l'azione viene eseguita su ogni riga,
altrimenti solo sulle righe che soddisfano la pattern.
Una pattern speciale BEGIN viene eseguita prima della prima riga; una
END, dopo l'ultima riga (BEGIN e END non sono combinabili con altre
pattern).  Altrimenti, le pattern sono espressioni regolari (come in
egrep) eventualmente connesse da operatori booleani (|| per OR, && per
AND, ! per NOT).
Ci possono essere due pattern separate da virgola: allora l'azione viene
eseguita in tutti i casi a partira da una riga che soddisfa la prima
pattern sino ad una che soddisfa la seconda (comprese).
Poi c'e` dell'altro (if, while, for, variabili, funzioni, ecc ecc) ma in
questo caso non serve (salvo eventualmente gsub che fa una sostituzione
globale, come la s/...//g di sed).
Una soluzione "puro awk" al tuo problema potrebbe dunque essere:
awk '{ gsub("\"", "") }
/TEL/
/Date/, /END/ { if (/END/) print "----"; else print }' $FILES
(puoi tenerla su di 1 sola riga cambiando i fineriga in puntievirgola,
se vuoi).  Perl e Ruby hanno un'opzione -n che permette di simulare
abbastanza da vicino il comportamento di Awk (Python invece non ha
queste scorciatoie per operare cicli da linea comando, e incoraggia a
mettere comunque il programma in un file -- cosa che in pratica si fa
anche in awk, perl e ruby per programmi di piu` di una o due
istruzioni).
Alex