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.
Rispondi
Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven 10 ago 2007, 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Lavoro per sed/awk

Messaggio da anycolouryoulike »

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
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Lavoro per sed/awk

Messaggio da targzeta »

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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven 10 ago 2007, 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggio da anycolouryoulike »

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: ven 10 ago 2007, 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggio da anycolouryoulike »

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
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Lavoro per sed/awk

Messaggio da targzeta »

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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven 10 ago 2007, 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Lavoro per sed/awk

Messaggio da anycolouryoulike »

Grazie mille, awk me lo devo proprio studiare...

Rispondi