Insert multiple lines into a file after specified pattern using shell script

137,081

Solution 1

Another sed,

sed '/cdef/r add.txt' input.txt

input.txt:

abcd
accd
cdef
line
web

add.txt:

line1
line2
line3
line4

Test:

sat:~# sed '/cdef/r add.txt' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

If you want to apply the changes in input.txt file. Then, use -i with sed.

sed -i '/cdef/r add.txt' input.txt

If you want to use a regex as an expression you have to use the -E tag with sed.

sed -E '/RegexPattern/r add.txt' input.txt

Solution 2

Using GNU sed:

sed "/cdef/aline1\nline2\nline3\nline4" input.txt

If you started with:

abcd
accd
cdef
line
web

this would produce:

abcd
accd
cdef
line1
line2
line3
line4
line
web

If you want to save the changes to the file in-place, say:

sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt

Solution 3

sed '/^cdef$/r'<(
    echo "line1"
    echo "line2"
    echo "line3"
    echo "line4"
) -i -- input.txt

Solution 4

Using awk:

awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt 

Explanation:

  • You find the line you want to insert from using /.../
  • You print the current line using print $0
  • RS is built-in awk variable that is by default set to new-line.
  • You add new lines separated by this variable
  • 1 at the end results in printing of every other lines. Using next before it allows us to prevent the current line since you have already printed it using print $0.

$ awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

To make changes to the file you can do:

awk '...' input.txt > tmp && mv tmp input.txt

Solution 5

Here is a more generic solution based on @rindeal solution which does not work on MacOS/BSD (/r expects a file):

cat << DOC > input.txt
abc
cdef
line
DOC
$ cat << EOF | sed '/^cdef$/ r /dev/stdin' input.txt
line 1
line 2
EOF

# outputs:
abc
cdef
line 1
line 2
line

This can be used to pipe anything into the file at the given position:

$ date | sed '/^cdef$/ r /dev/stdin' input.txt

# outputs
abc
cdef
Tue Mar 17 10:50:15 CET 2020
line

Also, you could add multiple commands which allows deleting the marker line cdef:

$ date | sed '/^cdef$/ {
  r /dev/stdin
  d
}' input.txt

# outputs
abc
Tue Mar 17 10:53:53 CET 2020
line
Share:
137,081

Related videos on Youtube

user27
Author by

user27

Updated on July 08, 2022

Comments

  • user27
    user27 almost 2 years

    I want to insert multiple lines into a file using shell script. Let us consider my input file contents are: input.txt:

    abcd
    accd
    cdef
    line
    web
    

    Now I have to insert four lines after the line 'cdef' in the input.txt file. After inserting my file should change like this:

    abcd
    accd
    cdef
    line1
    line2
    line3
    line4
    line
    web
    

    The above insertion I should do using the shell script. Can any one help me?

  • Sina
    Sina over 9 years
    Is there a way to do this the other way around (remove text found in add.txt from input.txt) ?
  • hdl
    hdl over 8 years
    I am new to sed but wow I am in love with its power! If you want to append an empty newline first you have to escape the backslash character after the append command like this : sed "/cdef/a\\\nline1\nline2\nline3\nline4" input.txt. I am not sure why it works like that though, if somebody could explain this would be nice!
  • CMCDragonkai
    CMCDragonkai over 8 years
    The current command inserts the line* on every mention of cdef, is there a way to make it so that it only inserts on the first time it encounters cdef and no more?
  • Mike Lutz
    Mike Lutz almost 6 years
    MacOS sed doesn't implement the a command precisely the same as GNU sed, so the above won't work in MacOS without mods - at least as of macOS 10.13 ( see unix.stackexchange.com/a/131940/230763 )
  • potong
    potong over 5 years
    A variation, that allows for an anonymous file is to pipe a here document into a sed invocation and use the r command to read from /dev/stdin.
  • Walter A
    Walter A over 5 years
    Missed this good answer. Shorter but less readable is sed '/^cdef$/r' <(printf "%s\n" line{1..4}) -i -- input.txt.
  • Hud
    Hud over 3 years
    Hi, is there a quick way to add 4 spaces before the added lines from add.txt ?
  • Ruli
    Ruli over 3 years
    Can you add some explanation to your command to help the future readers understand what has been done?
  • Luc
    Luc about 3 years
    <h1>there is no need to scream</h1>
  • Luc
    Luc about 3 years
    Note that this won't work in containers when you're issuing the command from the host, as the file descriptor from <(...) will be created on the host and not the guest. Using the /someline/a<added\ncontent> method works better, especially if you do something like sed "/someline/a$(echo 'here you can have newlines' | tr \\n @ | sed '\''s/@/\\n/g'\')" -i -- input.txt (not a full example and not properly tested, I don't have time for it now, but this should include the building blocks for what you need).