PDA

View Full Version : Piccolo aiuto con uno script


DigitalKiller
21-06-2007, 17:25
Devo scrivere un piccolo script di shell, che partendo da un file in questo formato:
V000001......................................
V000001......................................
V000001......................................
B000001......................................
B000001......................................
v000002......................................
B000002......................................
B000002......................................
v000002......................................
B000003......................................
B000003......................................
v000003......................................
B000003......................................
B000004......................................
v000004......................................
B000005......................................
B000005......................................
v00000n......................................

mi generi n file in quest'altro formato:

file000001:
V000001......................................
V000001......................................
V000001......................................
B000001......................................
B000001......................................

file000002:
v000002......................................
B000002......................................
B000002......................................
v000002......................................


file00000n:
v00000n......................................

In pratica, nello script devo indicare quali codici andare a cercare (000001, 000002, ecc), scorrere il file di partenza n volte e generare i file di destinazione.
Mi potreste dire come fare a ricercare la stringa nel file ed a copiare l'intera riga in un altro file? Il resto dello script vorrei provare a scriverlo da solo...
Grazie:D

Franco2
21-06-2007, 18:06
In pratica, nello script devo indicare quali codici andare a cercare (000001, 000002, ecc), scorrere il file di partenza n volte e generare i file di destinazione.


Non credo che serva scorrere il file n volte. Penso che basti usare sed e si risolve il problema. Ora provo a farlo:
Metto il tag spoiler se non vuoi vedere lo script completo.

#!/bin/bash

FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | sed 's/.\([^.]*\).*/\1/g')
done

Vedi un po' se funge... non l'ho testato.

DigitalKiller
21-06-2007, 18:25
Grazie per la risposta!:)
Ho provato il tuo script, ma non ottengo ciò che vorrei. Così com'è, lo script mi genera tanti file quante sono le righe e, mi sembra, anche per le colonne.:(
Forse mi sbaglio, ma credo che ti abbiano confuso quei puntini che ho inserito descrivendo il file.
Il file in questione è a formato fisso a 185 colonne e comprenden vari caratteri e spazi.
Ecco un esempio reale
V0000013605015SUCCO F.JOLLY PESCAX3 BRML0200 003158158005JOLLY X 3 8 53 8520MLLT 0,600 12 11 8002700219203 0 01 0 0 0 0 0

Grazie:)

Franco2
21-06-2007, 18:43
Forse ho capito. Riprova così:

#!/bin/bash

FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | cut -c 2-7)
done

DigitalKiller
21-06-2007, 19:05
Forse ho capito. Riprova così:

#!/bin/bash

FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | cut -c 2-7)
done


No, purtroppo lo script continua a generare 1 file per ogni riga ed ogni colonna. A me, invece, servirebbe un unico file in cui sono compiate tutte le righe con lo stesso codice (il codice sono i 6 caratteri dopo la V o la B)

Franco2
22-06-2007, 02:15
No, purtroppo lo script continua a generare 1 file per ogni riga ed ogni colonna.

AAAAh! Certo! Ci sono gli spazi che fanno danno! Prova così:


#!/bin/bash

IFS_BAK=$IFS
IFS=$'\n'
FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | cut -c 2-7)
done
IFS=$IFS_BAK

gurutech
22-06-2007, 10:27
AAAAh! Certo! Ci sono gli spazi che fanno danno! Prova così:


#!/bin/bash

IFS_BAK=$IFS
IFS=$'\n'
FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | cut -c 2-7)
done
IFS=$IFS_BAK


non credo che funzioni ... in questo modo non dividi i codici uno dall'altro.
innanzitutto non sappiamo a priori quanti sono i codici.
sappiamo solo che ogni codice e' formato da una lettera (che ci e' indifferente se ho capito bene) e 6 cifre. per cui dobbiamo selezionare tutti i codici numerici in un file e poi splittare in tanti file con ogni codice
con questo file di test:

gianluca@gurutech:~$ cat test
V000001ASDJHWIUJCNJ
V000002ASDJHWIUJCNJ
V000003ASDJHWIUJCNJ
V000001ASDJHWIUJCNJ
B000001ASDJHWIUJCNJ
B000002ASDJHWIUJCNJ

e questo script

gianluca@gurutech:~$ cat parse.sh
#!/bin/bash
# prendo l'inizio della riga, cerco una lettera e sei cifre
# scarto il resto tengo solo le cifre e le riordino per codici unici
cat test | sed -e "s/^[A-Za-z]\([0-9]\{6\}\).*/\1/" | sort -g | uniq |
while read CODICE; do {
# cerco tutto quello con quel codice e lo butto in un file
cat test | egrep "^[A-Za-z]$CODICE" > cod$CODICE.txt
}
done

ottengo

gianluca@gurutech:~$ cat cod000001.txt
V000001ASDJHWIUJCNJ
V000001ASDJHWIUJCNJ
B000001ASDJHWIUJCNJ
gianluca@gurutech:~$ cat cod000002.txt
V000002ASDJHWIUJCNJ
B000002ASDJHWIUJCNJ
gianluca@gurutech:~$ cat cod000003.txt
V000003ASDJHWIUJCNJ

kingv
22-06-2007, 10:35
gurutech> il tuo approccio se il file è grosso è molto lento perchè rifai lo scan del file n+1 volte (dove n è il numero dei codici). dato che tutte le informazioni di cui hai bisogno per "decidere" il file in cui mettere la riga sono contenute nella riga stessa è inutile.

gurutech
22-06-2007, 10:39
gurutech> il tuo approccio se il file è grosso è molto lento perchè rifai lo scan del file n+1 volte (dove n è il numero dei codici). dato che tutte le informazioni di cui hai bisogno per "decidere" il file in cui mettere la riga sono contenute nella riga stessa è inutile.

si ma come dividi? o guardi una riga per volta e con un >> lo appendi di volta in volta a file differenti, oppure guardi l'insieme e prendi il file a blocchi.
io ho scelto l'approccio a blocchi perchè mi pare più veloce.
tu come faresti?

gurutech
22-06-2007, 10:42
non credo che funzioni ... in questo modo non dividi i codici uno dall'altro.

comunque ho detto una cavolata e me ne scuso. l'approccio di Franco2 e' perfettamente funzionante...

DigitalKiller
22-06-2007, 12:21
AAAAh! Certo! Ci sono gli spazi che fanno danno! Prova così:


#!/bin/bash

IFS_BAK=$IFS
IFS=$'\n'
FILE_DI_PARTENZA=$1
for a in $(cat $FILE_DI_PARTENZA)
do
echo $a >> file$(echo $a | cut -c 2-7)
done
IFS=$IFS_BAK


Grande, funziona perfettamente!:D :D
Non credevo fosse così semplice:( Solo non riesco a capire come viene utilizzata la variabile IFS:rolleyes:
Comunque....devo proprio mettermi a studiare un po' di programmazione bash:muro: :D
Grazie per l'aiuto!:D

kingv
22-06-2007, 14:29
si ma come dividi? o guardi una riga per volta e con un >> lo appendi di volta in volta a file differenti, oppure guardi l'insieme e prendi il file a blocchi.
io ho scelto l'approccio a blocchi perchè mi pare più veloce.
tu come faresti?


proprio come dici tu, appendendo le righe a file di volta in volta differenti.
penso che come prestazioni sia migliore su file lunghi.
funzionalmente anche la tua soluzione è buona (ma è più da programmatore, non me la sari aspettata da te :D )

Franco2
22-06-2007, 16:36
Solo non riesco a capire come viene utilizzata la variabile IFS:rolleyes:


IFS è una variabile di sistema che, in pratica, indica per quali caratteri una lista viene divisa nei suoi elementi. Di default è definita dall'"a capo", dallo spazio, dal tab (e forse anche da qualche altra cosa, non ne sono sicuro). Scrivendo IFS=$'\n' gli si dice di considerare la fine dell'elemento solo per l'"a capo".
Poi, con l'ultima riga, lo si reimposta alla definizione standard.

kingv
22-06-2007, 22:43
Poi, con l'ultima riga, lo si reimposta alla definizione standard.


sì ma il salvataggio e ripristino del valore non serve a niente, la variabile e' locale allo script e non influenza la shell chiamante.

Franco2
23-06-2007, 05:09
sì ma il salvataggio e ripristino del valore non serve a niente, la variabile e' locale allo script e non influenza la shell chiamante.

Buono a sapersi, grazie. ;)