Sostituisci modello all'interno di un file con il contenuto di un altro file


20

Ho un file di testo ( devel.xml).

Ho aggiunto la parola REPLACETHIS ad esso per sostituire questa stringa con il contenuto all'interno di un file diverso ( temp.txt).

La cosa più vicina che ho è questa:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

Ciò inserisce il contenuto dopo la stringa e quindi elimina la stringa in seguito.

È questo il modo migliore per farlo?


Deve essere sed? A seconda della quantità di testo presente in temp.txt, potrei passare a una soluzione perl.
user17591,

Risposte:


34

Quello che hai fatto è rimuovere SUBSTITUTETHISovunque appare nel file (ma non il resto della riga in cui appare) e inserire il contenuto temp.TXTsotto quella riga. Se SUBSTITUTETHISappare più volte su una riga, viene rimossa solo la prima occorrenza e temp.TXTviene aggiunta una sola copia di .

Se si desidera sostituire l'intera riga quando SUBSTITUTETHISappare, utilizzare il dcomando. Dal momento che è necessario eseguire entrambi re dquando c'è una partita, metterli in un gruppo rinforzato.

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

Alcune implementazioni sed consentono di utilizzare i punti e virgola per separare i comandi e omettere del tutto i separatori attorno alle parentesi graffe, ma è comunque necessaria una nuova riga per terminare l'argomento con il rcomando:

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

Se si desidera sostituire SUBSTITUTETHIScon il contenuto del file, ma conservare ciò che viene prima e dopo sulla linea, è più complicato. Il metodo più semplice è includere il contenuto del file nel comando sed; nota che dovrai citare correttamente il suo contenuto.

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

Oppure usa Perl. Questo è breve ma viene eseguito catuna volta per ogni sostituzione:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

Per leggere il file una volta all'avvio dello script ed evitare a seconda di un comando shell:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

(presentato su due righe per leggibilità ma è possibile omettere l'interruzione di riga). Se il nome del file è variabile, per evitare problemi di quotazione, passalo allo script tramite una variabile di ambiente:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

Come potrei cambiare il comando perl in modo che invece di cat temp.txtfare cat ${variable}?
Maria Ines Parnisari,

@MariaInesParnisari Ho fatto un errore con la formattazione dei commenti. Vedi la mia risposta, con una soluzione leggermente diversa, più robusta.
Gilles 'SO- smetti di essere malvagio' il

Poiché File :: Slurp non è sempre installato, un'alternativa è quella di utilizzare l' -0777interruttore per bere l'intero file e un normale open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk

Come avvolgere r temp.TXTcon messaggi come "BEGIN temp.txt", "END temp.TXX"
KYB

Ho trovato una soluzione per la mia domanda. Usa il acomando (aggiungi). grymoire.com/Unix/Sed.html#uh-36
KYB
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.