Repository 32bit  Forum
Repository 64bit  Wiki

Lavoro per sed/awk

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

Lavoro per sed/awk

Messaggioda anycolouryoulike » mar ott 19, 2010 14:36

Devo sostituire in un file determinate linee con altre che si trovano in un altro file.
Nel primo file le linee sono identificabili con una regexp, mentre il secondo contiene solo le righe da sostituire.
Faccio un esempio per capire meglio. Il primo file è così:
Codice: Seleziona tutto
afdsaf
afdfad
afdfa
B adfadfa
adfda
fadsfa
fadsf
B adfafd
Il secondo:
Codice: Seleziona tutto
B prova prova
B ciao ciao
Vorrei ottenere:
Codice: Seleziona tutto
afdsaf
afdfad
afdfa
B prova prova
adfda
fadsfa
fadsf
B ciao ciao
Ho provato con questo:
Codice: Seleziona tutto
sed '/^B /{z;R file2}' file1
ma ottengo:
Codice: Seleziona tutto
sed: -e expression #1, char 0: unmatched `{'
Qualcuno ha idea di come fare in modo semplice?
Grazie
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggioda targzeta » mar ott 19, 2010 15:55

L'algoritmo è corretto, solo che devi stare attento a due cose:
  • Il comando 'd' elimina il pattern space e fa ricominciare il ciclo, quindi il tuo comando 'R' non sarà mai eseguito.
  • Il comando 'R' prende come argomento il nome del file, ma come fa a sapere quando finisce il nome del file? Generalmente quando arriva il '\n'.
Quindi il tuo script diventerebbe:
Codice: Seleziona tutto
sed '/^B /{R file2
;d}' file1
Dopo che hai scritto il nome del file premi pure invio, dato che hai inserito un apice prima dell'espressione la shell non invoca il comando ma va a capo ed attende l'altro apice di chiusura.

L'errore era dovuto al fatto che il comando 'R' si prendeva anche la parentesi chiusa come parte del nome del file e quindi, giustamente, sed lamentava l'assenza di una parentesi.

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6189
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Lavoro per sed/awk

Messaggioda anycolouryoulike » mar ott 19, 2010 16:01

Si il d poi l'ho cambiato con una z...
Come dici tu comunque è perfetto.
Intuivo che il problema era quello del nome del file, infatti ho provato anche (invano) a quotare la parentesi.
Grazie davvero!
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggioda anycolouryoulike » mar ott 19, 2010 20:33

Ci sarebbe anche un altro lavoretto, che credo sia più comodo fare con awk (che non conosco quasi per niente).
Vorrei dividere quello stesso file in dei file più piccoli, ognuno dei quali termina con la riga che inizia con B.
Qualche idea? Sicuramente non dev'essere difficile.
Grazie
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggioda targzeta » mer ott 20, 2010 6:34

Non ho capito se vuoi sempre fare la sostituzione precedente o no. In questo caso è meglio usare awk perché ogni file ha un nome diverso e quindi serve incrementare una variabile.

Io ho pensato a questa soluzione:
Codice: Seleziona tutto
awk 'BEGIN {i=0} /^B /{getline < "file1"} {print $0 >> "file_tmp" i} /^B /{i++}' file
il codice sopra esegue anche la sostituzione che avevi richiesto all'inizio.

Altrimenti, se non vuoi più sostituire le regex ma solo spezzettare il file:
Codice: Seleziona tutto
awk 'BEGIN {i=0} {print $0 >> "file_tmp" i} /^B /{i++}' file

In entrambi i casi:
  • file è il file di input
  • file1 è l'eventuale file da cui prendere le stringhe da sostituire alle regex
  • file_tmp[0...N] contengono i pezzi di file

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6189
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Lavoro per sed/awk

Messaggioda anycolouryoulike » mer ott 20, 2010 15:34

Grazie mille, awk me lo devo proprio studiare...
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti