Remplacer le modèle d'un fichier par le contenu d'un autre fichier

20

J'ai un fichier texte ( devel.xml).

Je lui ai ajouté le mot REPLACETHIS afin de remplacer cette chaîne par le contenu d'un fichier différent ( temp.txt).

La chose la plus proche que j'ai est la suivante:

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

Cela insère le contenu après la chaîne, puis supprime la chaîne par la suite.

Est-ce la meilleure façon de le faire?

RafaelGP
la source
Doit-il être séduit? Selon la quantité de texte dans temp.txt, je pourrais passer à une solution perl.
user17591

Réponses:

34

Ce que vous avez fait est de supprimer l' SUBSTITUTETHISendroit où il apparaît dans le fichier (mais pas le reste de la ligne où il apparaît) et d'insérer le contenu temp.TXTsous cette ligne. Si SUBSTITUTETHISapparaît plusieurs fois sur une ligne, seule la première occurrence est supprimée et une seule copie de temp.TXTest ajoutée.

Si vous souhaitez remplacer la ligne entière lorsque SUBSTITUTETHISs'affiche, utilisez la dcommande. Puisque vous devez exécuter les deux ret dquand il y a un match, mettez-les dans un groupe contreventé.

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

Certaines implémentations sed vous permettent d'utiliser des points-virgules pour séparer les commandes et d'omettre complètement les séparateurs autour des accolades, mais vous avez toujours besoin d'une nouvelle ligne pour terminer l'argument de la rcommande:

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

Si vous voulez remplacer SUBSTITUTETHISpar le contenu du fichier, mais conserver ce qui vient avant et après sur la ligne, c'est plus compliqué. La méthode la plus simple consiste à inclure le contenu du fichier dans la commande sed; notez que vous devrez citer correctement son contenu.

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

Ou utilisez Perl. Ceci est court mais s'exécute catune fois pour chaque substitution:

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

Pour lire le fichier une fois au démarrage du script et éviter de dépendre d'une commande shell:

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

(présenté sur deux lignes pour plus de lisibilité mais vous pouvez omettre le saut de ligne). Si le nom de fichier est variable, pour éviter de citer des problèmes, transmettez-le au script via une variable d'environnement:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt
Gilles 'SO- arrête d'être méchant'
la source
Comment pourrais-je changer la commande perl pour qu'au lieu de cat temp.txtje puisse faire cat ${variable}?
Maria Ines Parnisari
@MariaInesParnisari J'ai fait une erreur avec la mise en forme des commentaires. Voir ma réponse, avec une solution légèrement différente et plus robuste.
Gilles 'SO- arrête d'être méchant'
Étant donné que File :: Slurp n'est pas toujours installé, une alternative consiste à utiliser le -0777commutateur pour slurp dans tout le fichier, et un régulier open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk
Comment boucler r temp.TXTavec des messages comme "BEGIN temp.TXT", "END temp.TXX"
kyb
J'ai trouvé une solution à ma question. Utilisez la acommande (ajouter). grymoire.com/Unix/Sed.html#uh-36
kyb