Comment remplacer une partie d'un fichier texte entre des marqueurs par un autre fichier texte?


26

Disons que j'ai un fichier texte comme celui-ci:

# custom content section
a
b

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

Je voudrais remplacer la partie entre les GENERATED CONTENTbalises par le contenu d'un autre fichier.

Quelle est la manière la plus simple de procéder?

Réponses:


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

Excellent. sedpeut faire bien plus que juste s/.../...!
DevSolar

Hmmm ne fonctionne pas pour moi, dois-je mettre la commande sed sur une seule ligne?
lzap

3
La r insert_filecommande doit être la dernière chose sur sa ligne. Notez que ni les espaces ni les commentaires ne sont autorisés après. Le code a été testé en utilisant GNU sedavec l' --posixoption activée, et il a fonctionné comme prévu, donc il devrait fonctionner avec n'importe quel compatible posix sed .
Peter.O

1
Holy moly, c'est cool! Cela va dans mon dictionnaire sed! Superbement utile et magnifiquement simple. Merci!
DanielSmedegaardBuus

2
Notez qu'une modification sur place nécessite que vous capturiez la sortie de sed (par exemple output=$(sed -e "..." existing_file)), puis effectuez le remplacement dans un deuxième passage (par exemple echo "$output" > existing_file) car essayer de rediriger vers un fichier que vous lisez le fera tronquer avant la lecture du contenu.
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

Bon travail. Beaucoup plus simple que le mien. :)
Dr Kitty

4

Avertissement: ce n'est certainement pas la façon la plus simple de le faire. (EDIT: bash fonctionne; grep POSIX est très bien aussi)

Si le texte principal se trouve dans le fichier "main" et que le contenu généré est dans le fichier "gen", vous pouvez procéder comme suit:

#!/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

Est-ce que ça marche? Je pense que votre dernière ligne s'ouvrira mainpour l'écriture, l'effaçant, avant qu'elle ne soit lue par le chat.
chepner

@chepner Crap, vous avez raison. Le reste fonctionne, cependant. Je le réparerai.
Dr Kitty

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

Utilisation d'un hérédoc et de l'éditeur de ligne ed. La première ligne à l'intérieur de l'hérédoc doit supprimer 'd' la ligne après '+' la '### BEGIN gENERATED ...' et la ligne avant '-' la '### END GENERATED ...' la deuxième ligne consiste à insérer FILE2 après la ligne ### END GENERATED ... '
Jetchisel

désolé ce que je voulais dire était d'insérer FILE2 après la ligne '### BEGIN GENERATED ..'
Jetchisel

Allez-y doucement, c'est après tout ma première fois :-). Aussi, j'aurais peut-être utilisé le même mot, mais l'autre solution n'utilise pas un heredocs mais un printf et un pipe. Toutes
mes

Merci, très lisible! Btw - au lieu de r FILE2vous pouvez dire r !commandde lire à partir d'un script différent.
Kos
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.