Etienne Bruines
Etienne Bruines

Reputation: 3038

Sed replace pattern with file contents

I would like to use sed (I think?) to replace a pattern with file contents.

Example

File 1 (primary file)

Hello <<CODE>>
Goodbye.

File 2 (contents)

Anonymous person,
I am very nice. 

File 3 (target)

Hello Anonymous person,
I am very nice.
Goodbye.

Right now, I am using this command:

sed "/<<CODE>>/{r file2
:a;n;ba}" file1            | \
    sed "s/<<CODE>>//g"    > \
    file3

But this outputs:

Hello
Anonymous person,
I am very nice.
Goodbye.

(note the newline after Hello)

Upvotes: 4

Views: 1987

Answers (5)

αғsнιη
αғsнιη

Reputation: 2761

You could do simply with:

awk '{gsub("<<CODE>>", filetwo)}1' filetwo="$(<file2)" file1

Upvotes: 1

anubhava
anubhava

Reputation: 784918

Much simpler to use awk:

awk 'FNR==NR{s=(!s)?$0:s RS $0;next} /<<CODE>>/{sub(/<<CODE>>/, s)} 1' file2 file1
Hello Anonymous person,
I am very nice.
Goodbye.

Explanation:

  • FNR==NR - Execute this block for first file in input i.e. file2
  • s=(!s)?$0:s RS $0 - Concatenate whole file content in string s
  • next - Read next line until EOF on first file
  • /<<CODE>>/ - If a line with <<CODE>> is found execute that block
  • sub(/<<CODE>>/, s) - Replace <<CODE>> with string s (data of file2)
  • 1 - print the output

EDIT: Non-regex way:

awk 'FNR==NR{s=(!s)?$0:s RS $0; next}
     i=index($0, "<<CODE>>"){$0=substr($0, 1, i-1) s substr($0, i+8)} 1' file2 file1

Upvotes: 3

Jason Hu
Jason Hu

Reputation: 6333

not too bad in Perl:

 cat file1 | perl -e "open FH, qq(file2); \$f2=join '', <FH>; chomp \$f2; map {s/<<CODE>>/\$f2/g; print \$_} <STDIN>" > file3

(maybe i am not the best perl coder)

it's straight-forward. read the whole file2 in, substitute it, then print.

Upvotes: 1

jaybee
jaybee

Reputation: 955

I am thinking about a solution where we use Bash to evaluate a cat process outside of the single quotes delimitating the sed script, but unfortunately the following doesn't work as soon as your file2 contains a newline:

sed 's/<<CODE>>/'"$(cat file2)"'/' file1

It accepts spaces in file2, but not newlines, as you can see in the following piece of code that works well, whatever the content of file2:

sed 's/<<CODE>>/'"$(cat file2 | tr -d '\n')"'/' file1

But, obviously, this modifies the content of the file before inclusion, which is simply bad. :-(

So if you want to play, you can first tr the newlines to some weird unexpectable character, and translate those back after sed has worked on its script:

sed 's/<<CODE>>/'"$(cat file2 | tr '\n' '\3')"'/' file1 | tr '\3' '\n'

Upvotes: 0

mr rogers
mr rogers

Reputation: 3260

The awk though it might be harder to read, is probably the right way to go.

Just for comparison sake, here's a ruby version

ruby -ne 'BEGIN{@body=File.open("file2").read}; puts gsub(/<<CODE>>/,@body);' < file1

Upvotes: 1

Related Questions