18

I'm new to sed, I'm trying to insert the content of a BFile into the file AFile, BEFORE a pattern (in AFile)

Hereafter's what I've tried :

sed -i '/blah Blah/r BFile' AFile : it's inserting the content of BFile AFTER the pattern in AFile.

sed -i '/blah Blah/i BFile' AFile : it's inserting the string 'BFile' BEFORE the pattern in AFile.

... hmmm

I'm conscious it's because of a wrong comprehension of regexp or sed : I can't understand how the /i and /r work here... I can't find any help in sed --help

Anyone understanding my point ?

Regards,

Stan

St3an
  • 726
  • 1
  • 6
  • 21

7 Answers7

27

This might work for you (GNU sed):

sed $'/blah Blah/{e cat BFile\n}' AFile

or:

sed -e 'N;/\n.*blah Blah/{r BFile' -e '};P;D' AFile

or as Alek pointed out:

sed '/blah Blah/e cat BFile' AFile
potong
  • 55,640
  • 6
  • 51
  • 83
  • 2
    @NeronLeVelu this is a GNU sed specific command see [here](http://www.gnu.org/software/sed/manual/sed.html#Extended-Commands) – potong Oct 01 '14 at 14:21
  • 1
    Great answer, thanks! Why not just `sed '/blah Blah/e cat Bfile'` – Alek Feb 15 '21 at 15:10
  • This insert the contents of `BFile` on the *line* before the pattern. In my case I was trying to replace a pattern with a file. Which is `sed -e '/blah Blah/{r bar' -e 'd}'`. It's worth noting the `r` command needs to be escaped by a newline or a separate -e `...}`src https://askubuntu.com/a/540538/676225 – CervEd Dec 17 '21 at 21:35
  • @Alek I imagine invoking `cat` is would be less performant – CervEd Dec 17 '21 at 21:41
5

Content of AFile

one
two
three
blah Blah
four

Content of BFile

...b...

Run these commands

# get line number
$ sed -n '/blah Blah/=' AFile
4

# read file just before that line
$ sed '3r BFile' AFile
one
two
three
...b...
blah Blah
four
kev
  • 155,172
  • 47
  • 273
  • 272
  • 1
    While all the other sed command do not work if it is the last line, this one does. However this does not work if it is the first line. :( I guess you should chain this using an or `|` and call sed a third time if its the first line. – Andy Feb 04 '20 at 22:40
5

sed's r command does not change the pattern space. The file's content is printed at the end of the current cycle or when the next input line is read (info sed), therefore the N in the following command

sed '/blah Blah/ {
r Bfile
N
}' Afile
FrankL
  • 374
  • 4
  • 5
  • This answer is simpler without GNU sed. NOTE: this doesn't work when `/blah Blah/` is the last line (with newline terminator) in `Afile`, because it will append `Bfile` **after**, not before `blah Blah`. – Johnny Wong Nov 13 '18 at 02:50
3

[Insert file contents into another file BEFORE pattern]

sed -i '/PATTERN/r file1' -e //N file2

[After Pattern]

sed -i '/PATTERN/r file1' file2
kyun
  • 9,710
  • 9
  • 31
  • 66
Jim.Y
  • 31
  • 4
1

Just use awk:

Print Bfile before the matched line:

awk 'NR==FNR{bfile = bfile $0 RS; next} /blah Blah/{printf "%s", bfile} {print}' Bfile Afile

print Bfile after:

awk 'NR==FNR{bfile = bfile $0 RS; next} {print} /blah Blah/{printf "%s", bfile}' Bfile Afile
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0
sed '/blah Blah/ r BFile;x;1!p;${g;p;}' AFile

buffer the current line so read BFile occur before printing the current line (that is print a next line in fact)

NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43
0

Here were the solutions that worked for me:

  1. Using a marker like explained in another reply to a similar question:

    sed '/blah Blah/i MARKER' AFile | sed -e '/MARKER/r BFile' -e '/MARKER/d'
    
  2. Counting the line when it occured like explained in another reply:

    LINE_NUMBER_MATCHING=$(sed -n '/blah Blah/=' AFile) && sed "$((${LINE_NUMBER_MATCHING} - 1))r BFile" AFile
    
  3. Or using sed like explained in another reply:

    sed $'/blah Blah/{e cat BFile\n}' AFile
    
Anthony O.
  • 22,041
  • 18
  • 107
  • 163