26

I have two different files:

File1

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

File2

<TEXT1>
<TEXT2>

I want to replace the <TEXT1> of File2 with the contents of File1 using sed. I tried this command, but not getting proper output:

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

You can use other tools also to solve this problem.

6
  • Please paste that error message so we can locate its source. Also tell us which sed implementation are you using. You code works for me with GNU sed.
    – manatwork
    Commented Sep 8, 2011 at 14:40
  • Sorry, Not getting an error. I am not getting desired output. Output is like /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. Not getting new lines. Commented Sep 8, 2011 at 14:51
  • Not sure if this would apply in your specific case, but with diff and patch tools allow to replace some lines in a file by other lines quite easily. Commented Sep 8, 2011 at 14:54
  • 1
    Btw, using random data gathered with $() in a sed script makes my eyes bleed. Never use external data in places where some characters are interpreted with special meaning. Commented Sep 8, 2011 at 14:59
  • Similar question: Substitute pattern within a file with the content of other file Commented Aug 2, 2016 at 9:36

3 Answers 3

25

Here's a sed script solution (easier on the eyes than trying to get it into one line on the command line):

/<TEXT1>/ {
  r File1
  d
}

Running it:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>
6
  • Thanks this is working. But I don't want to use any other script file. Are there any inline solution? Commented Sep 8, 2011 at 14:57
  • Sure: sed '/<TEXT1>/{rFile1^Md^M}' File2, where "^M" is you pressing return. The problem is that sed really needs the newlines within the {...} to delimit the r and the d command.
    – Kusalananda
    Commented Sep 8, 2011 at 15:46
  • 6
    with bash, posix-style strings are a bit cleaner: sed $'/<TEXT1>/ {r File1\n d}' Commented Sep 8, 2011 at 17:18
  • 9
    Also with -e for a one liner: sed -e '/<TEXT1>/{r File1' -e 'd}' File2
    – sdaau
    Commented Jun 7, 2012 at 14:12
  • 1
    And what if instead of replacing the entire line containing <TEXT1>, I just want to replace the string itself, leaving the rest of the line intact? Text1: <TEXT1> to Text1: <file_contents>. Commented May 10, 2014 at 17:13
14

Took me a long time to find this solution using var replacement. All sed solutions did not work for me, as they either delete complete lines or replace incorrectly.

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

Replaces all occurences of TEXT1 in file2 against content of file1. All other text remains untouched.

2
  • very nice. possibly faster than sed too, since those "expansions" (aka replacements) are built into the shell (bash at least) Commented Nov 25, 2019 at 21:17
  • Thank you! You can pip multiple files to this genius method using a while read method described here
    – Mossab
    Commented Jan 5, 2023 at 16:51
7

I answer because the diff/patch method might be of interest in some cases. To define a substitution of lines contained in file blob1 by lines contained in blob2 use:

diff -u blob1 blob2 > patch-file

For example, if blob1 contains:

hello
you

and blob2 contains:

be
welcome
here

the generated patch-file will be:

--- 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

Now, you can apply this patch to any other file:

patch somefile patch-file

It will replace hello,you lines by be,welcome,here lines in somefile.

1
  • this is really clever but would be better if you could automate it in a script
    – qodeninja
    Commented Jun 24, 2018 at 2:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .