Remplacer la chaîne par le contenu d'un fichier à l'aide de sed

23

J'ai deux fichiers différents:

File1

/home/user1/  
/home/user2/bin  
/home/user1/a/b/c

File2

<TEXT1>
<TEXT2>

Je veux remplacer le <TEXT1>de File2 par le contenu de File1 en utilisant sed. J'ai essayé cette commande, mais je n'ai pas obtenu de sortie appropriée:

cat File2|sed "s/<TEXT1>/$(cat File1|sed 's/\//\\\//g'|sed 's/$/\\n/g'|tr -d "\n")/g"

Vous pouvez également utiliser d'autres outils pour résoudre ce problème.

chanchal1987
la source
Veuillez coller ce message d'erreur afin que nous puissions localiser sa source. Dites-nous également quelle sedimplémentation utilisez-vous. Votre code fonctionne pour moi avec GNU sed.
manatwork
Désolé, pas d'erreur. Je n'obtiens pas la sortie souhaitée. La sortie est comme /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. Pas de nouvelles lignes.
chanchal1987
Je ne sais pas si cela s'appliquerait dans votre cas spécifique, mais avec diffet les patchoutils permettent de remplacer assez facilement certaines lignes d'un fichier par d'autres lignes.
Stéphane Gimenez
1
Btw, en utilisant des données aléatoires recueillies $()dans un script sed me fait saigner les yeux. N'utilisez jamais de données externes dans des endroits où certains caractères sont interprétés avec une signification particulière.
Stéphane Gimenez

Réponses:

24

Voici une solution de script sed (plus facile à regarder que d'essayer de la mettre en une seule ligne sur la ligne de commande):

/<TEXT1>/ {
  r File1
  d
}

Exécuter:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>
Kusalananda
la source
Merci, cela fonctionne. Mais je ne veux utiliser aucun autre fichier de script. Existe-t-il une solution en ligne?
chanchal1987
Bien sûr:, sed '/<TEXT1>/{rFile1^Md^M}' File2où "^ M" vous appuyez sur Entrée. Le problème est que sed a vraiment besoin des sauts de ligne dans le {...} pour délimiter les commandes r et d.
Kusalananda
6
avec bash, les cordes de style posix sont un peu plus propres:sed $'/<TEXT1>/ {r File1\n d}'
glenn jackman
9
Également avec -e pour un sed -e '/<TEXT1>/{r File1' -e 'd}' File2
aller simple
1
Et si au lieu de remplacer la ligne entière contenant <TEXT1>, je veux juste remplacer la chaîne elle-même, en laissant le reste de la ligne intact? Text1: <TEXT1>à Text1: <file_contents>.
Robin Winslow
9

Cela m'a pris beaucoup de temps pour trouver cette solution en utilisant le remplacement var. Toutes les solutions sed ne fonctionnaient pas pour moi, car elles supprimaient des lignes complètes ou remplaçaient incorrectement.

FILE2=$(<file2)
FILE1=$(<file1)
echo "${FILE2//TEXT1/$FILE1}" 

Remplace toutes les occurrences de TEXT1 dans le fichier2 par le contenu du fichier1. Tout autre texte reste intact.

marcas756
la source
très agréable. peut-être plus vite que sedtrop, car ces "extensions" (alias remplacements) sont intégrées dans la coque ( bashau moins)
jaune moelleux
7

Je réponds car la méthode diff/ patchpeut être intéressante dans certains cas. Pour définir une substitution des lignes contenues dans le fichier blob1par des lignes contenues dans l' blob2utilisation:

diff -u blob1 blob2 > patch-file

Par exemple, si blob1contient:

hello
you

et blob2contient:

be
welcome
here

le généré patch-filesera:

--- blob1   2011-09-08 16:42:24.000000000 +0200
+++ blob2   2011-09-08 16:50:48.000000000 +0200
@@ -1,2 +1,3 @@
-hello
-you
+be
+welcome
+here

Maintenant, vous pouvez appliquer ce patch à n'importe quel autre fichier:

patch somefile patch-file

Il remplacera hello, youlignes par be, welcome, herelignes somefile.

Stéphane Gimenez
la source
c'est vraiment intelligent mais ce serait mieux si vous pouviez l'automatiser dans un script
qodeninja