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.

chanchal1987
  • 686
  • 3
  • 9
  • 16
  • 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 Sep 08 '11 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 `. Not getting new lines. – chanchal1987 Sep 08 '11 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. – Stéphane Gimenez Sep 08 '11 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. – Stéphane Gimenez Sep 08 '11 at 14:59
  • Similar question: [Substitute pattern within a file with the content of other file](/q/49377) – Toby Speight Aug 02 '16 at 09:36
  • Possible duplicate of [How to replace text between two markers in a file with a section of text from another file?](https://unix.stackexchange.com/questions/212009/how-to-replace-text-between-two-markers-in-a-file-with-a-section-of-text-from-an) – Kusalananda Jun 07 '17 at 09:58

3 Answers3

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>
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • Thanks this is working. But I don't want to use any other script file. Are there any inline solution? – chanchal1987 Sep 08 '11 at 14:57
  • Sure: `sed '//{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 Sep 08 '11 at 15:46
  • 6
    with bash, posix-style strings are a bit cleaner: `sed $'// {r File1\n d}'` – glenn jackman Sep 08 '11 at 17:18
  • 9
    Also with [-e](http://www.unix.com/shell-programming-scripting/31092-replace-string-content-another-file.html#4) for a one liner: `sed -e '//{r File1' -e 'd}' File2` – sdaau Jun 07 '12 at 14:12
  • 1
    And what if instead of replacing the entire line containing ``, I just want to replace the string itself, leaving the rest of the line intact? `Text1: ` to `Text1: `. – Robin Winslow May 10 '14 at 17:13
  • @RobinWinslow - you could use any of the working solutions [here](http://unix.stackexchange.com/q/172399) (you will just have to slightly adjust the code to replace the pattern instead of appending after pattern). – don_crissti Apr 15 '15 at 15:51
13

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.

marcas756
  • 131
  • 1
  • 4
  • very nice. possibly faster than `sed` too, since those "expansions" (aka replacements) are built into the shell (`bash` at least) – mellow-yellow Nov 25 '19 at 21:17
  • Thank you! You can pip multiple files to this genius method using a `while read` method described [here](https://stackoverflow.com/a/33079920/13415228) – Mossab Jan 05 '23 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.

Stéphane Gimenez
  • 28,527
  • 3
  • 76
  • 87