Come sostituire parte di un file di testo tra marcatori con un altro file di testo?


26

Di 'che ho un file di testo come questo:

# custom content section
a
b

### BEGIN GENERATED CONTENT
c
d
### END GENERATED CONTENT

Vorrei sostituire la parte tra i GENERATED CONTENTtag con il contenuto di un altro file.

Qual è il modo più semplice per farlo?

Risposte:


36
lead='^### BEGIN GENERATED CONTENT$'
tail='^### END GENERATED CONTENT$'
sed -e "/$lead/,/$tail/{ /$lead/{p; r insert_file
        }; /$tail/p; d }"  existing_file

Eccellente. sedpuò fare molto di più di un semplice s/.../...!
DevSolar il

Hmmm non funziona per me, dovrei mettere il comando sed su una riga?
lzap,

3
Il r insert_filecomando deve essere l'ultima cosa sulla sua riga. Si noti che non sono consentiti né spazi bianchi né commenti. Il codice è stato testato usando GNU sedcon l' --posixopzione abilitata e ha funzionato come previsto, quindi dovrebbe funzionare con qualsiasi posix compatibile sed .
Peter

1
Santo cielo, è fantastico! Questo sta andando nel mio dizionario sed! Incredibilmente utile e meravigliosamente semplice. Grazie!
DanielSmedegaardBuus

2
Nota una modifica sul posto richiede l'acquisizione dell'output di sed (ad esempio output=$(sed -e "..." existing_file)) e quindi la sostituzione in un secondo passaggio (ad esempio echo "$output" > existing_file) poiché il tentativo di reindirizzare in un file da cui stai leggendo lo farà troncare prima che i contenuti vengano letti.
Chris Tonkinson,

5
newContent=`cat new_file`
perl -0777 -i -pe "s/(### BEGIN GENERATED CONTENT\\n).*(\\n### END GENERATED CONTENT)/\$1$newContent\$2/s" existing_file

Bel lavoro. Molto più semplice del mio. :)
Dr Kitty,

4

Attenzione: questo non è sicuramente il modo più semplice per farlo. (EDIT: bash funziona; anche POSIX grep va bene)

Se il testo principale è nel file "principale" e il contenuto generato è nel file "gen", è possibile effettuare le seguenti operazioni:

#!/bin/bash
BEGIN_GEN=$(cat main | grep -n '### BEGIN GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
END_GEN=$(cat main | grep -n '### END GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
cat <(head -n $(expr $BEGIN_GEN - 1) main) gen <(tail -n +$(expr $END_GEN + 1) main) >temp
mv temp main

funziona? Penso che la tua ultima riga si aprirà mainper la scrittura, cancellandola, prima che venga letta dal gatto.
Chepner,

@chepner Crap, hai ragione. Il resto funziona, però. Lo aggiusterò.
Dr Kitty,

3
ed -s FILE1 <<EOF
/### BEGIN GENERATED/+,/### END GENERATED/-d
/### BEGIN GENERATED/ r FILE2
w
q
EOF

Usando un heredoc e l'editor di riga ed. La prima riga all'interno dell'ereditarietà è eliminare 'd' la riga dopo '+' il '### INIZIA GENERATO ...' e la riga prima di '-' il '### END GENERATO ...' la seconda riga è inserire FILE2 dopo la riga ### END
GENERATED

scusate cosa volevo dire era inserire FILE2 dopo la riga '### INIZIA GENERATO ..'
Jetchisel,

Vacci piano con me gente, dopo tutto è la mia prima volta :-). Inoltre avrei potuto usare la stessa parola, ma l'altra soluzione non usa un heredocs ma un printf e una pipe. In ogni caso, mi
scuso

Grazie, molto leggibile! A proposito - invece di r FILE2te puoi dire r !commanddi leggere da una sceneggiatura diversa.
Kos,
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.