Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

File1 contents:

line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 

File2 contents:

line1-file2     "25"  
line2-file2     "24"  
Pointer-file2   "23"  
line4-file2     "22" 
line5-file2     "21"

After the execution of perl/shell script, File2 content should become:

line1-file2     "25"  
line2-file2     "24" 
line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 
Pointer-file2   "23" 
line4-file2     "22" 
line5-file2     "21"

i.e paste the contents of File1 in File2 before the line that contains "Pointer".

share|improve this question
Also asked at StackOverflow – glenn jackman Feb 28 '12 at 11:37

7 Answers 7

up vote 12 down vote accepted

sed has a function for that, and can do the modification inline:

sed -i -e '/Pointer/r file1' file2

But this puts your Pointer line above the file1. To put it below, delay line output:

sed -n -i -e '/Pointer/r file1' -e 1x -e '2,${x;p}' -e '${x;p}' file2 
share|improve this answer
Could you please explain what -e 1x -e '2,${x;p}' -e '${x;p}' do ? I understand that you exchange stuff in the pattern buffer and then print it but I don't know what nor why you added the quiet option -n at the beginning. – hdl Sep 24 at 14:47

Without using sed or awk...

First, find your the line on which is your pattern:

line=$(grep -n 'Pointer' file2 | cut -d ":" -f 1)

Then, use 3 commands to output the wanted result:

{ head -n $(($line-1)) file2; cat file1; tail -n +$line file2; } > new_file

This has the drawback of accessing 3 times the file file2, but might be clearer than a sed of awk solution.

share|improve this answer

Use a loop to read the lines in file2. If you find a line starting with Pointer, then print out file1. This is shown below:

while IFS= read -r line
    if [[ "$line" =~ ^Pointer.*$ ]]
        cat file1
    echo "$line"
done < file2
share|improve this answer

awk makes this fairly easy.
Insert the line before the file:

awk '/Pointer/{while(getline line<"innerfile"){print line}} //' outerfile >tmp
mv tmp outerfile

To make the inner file print after the Pointer line, just switch the order of the patterns (you need to add a semicolon to get the default action), and you can drop the line variable:

awk '//; /Pointer/{while(getline<"innerfile"){print}}' outerfile >tmp
mv tmp outerfile

And just because no one has used perl yet,

# insert file before line
perl -e 'while(<>){if($_=~/Pointer/){system("cat innerfile")};print}' outerfile

# after line
perl -e 'while(<>){print;if($_=~/Pointer/){system("cat innerfile")}}' outerfile
share|improve this answer
its working, but its getting removed the line containing pointer – user1228191 Feb 28 '12 at 18:18
likewise, how to Paste the contents of file 1 in file 2 after that "Pointer" containing line using awk – user1228191 Feb 28 '12 at 18:21
@user1228191 Fixed the first, added the second. – Kevin Feb 28 '12 at 18:42

There are a few ways to go about this w/ sed. One way is a delayed read as is recommended in the accepted answer. It could also be written like:

sed -e '$!N;P;/\nPointer/r file1' -e D file2

...with a little explicit look-ahead instead of the look-behind implemented elsewhere with the hold buffer. That will inevitably have the same problem with the last line that @don_crissti notes, though, because N does increment the line cycle and the read command is applied by line number.

You can get around it:

echo | sed -e '$d;N;P;/\nPointer/r file1' -e D file2 -

Not all seds will interpret the - to mean standard input, but many do. (POSIX says sed should support - to mean standard-in if the implementer wants - to mean standard-in???)

Another way is to handle the appended content in order. There is another command that schedules output in the same way read does, and sed will apply it and read in the order they're scripted. It's a little more involved though - it entails using one sed to append the Pointer match to the output of another sed in its script.

sed '   /Pointer/!d                  #only operate on first match
        s/[]^$&\./*[]/\\&/g;H        #escape all metachars, Hold
        s|.*|/&/!p;//!d|p;g          #print commands, exchange
        s|.|r file1&a\\&|;q' file2|  #more commands, quit
        sed -nf - file2              #same input file

So basically the first sed writes the second sed a script, which the second sed reads on standard-input (maybe...) and applies in turn. The first sed only works on the first match for Pointer found, and afterward quits input. Its job is to...

  1. s/[]^$&\./*[]/\\&/g;H
    • Make sure that all pattern chars are safely backslash-escaped because the second sed is going to need to interpret every bit it reads literally to get it right. Once that's done, put a copy in Hold space.
  2. s|.*|/&/!p;//!d|p; x
    • Tell the second sed to print every input line !but the /&/ one we just pattern-safed; and then to delete all of the same. print the commands at the second sed, then exchange the hold and pattern buffers to work on our saved copy.
  3. s|.|r file1&a\\&|p;q
    • The only char we work with here is a \newline because sed will have prepended one when we Held the line before. So we insert the command r file1 and follow it with our \newline then the command a\\ for append followed also by a \newline. All of the rest of our Held line follows that last \newline.

The script that the first writes looks something like this:

/Pointer-file2   "23"/!p;//!d
r file1
Pointer-file2   "23"

Basically the second sed will print every line but the one the first sed sets it up to append. For that particular line two delayed writes to standard-out are scheduled - the first is the read of file1 and the second is a copy of the line we want after it. The first sed's doctoring isn't even necessary in this case (see? no backslashes) but it is important to safely escape in the way I do here whenever a pattern match is repurposed as input.

Anyway, so... there are a few ways.

share|improve this answer

An easy job for ed:

ed -s file1 <<IN
/Pointer/-r file2

-r file1 reads in the specified file to after the addressed line, which in this case is the line previous to the first line matching Pointer. So this will insert the content of file2 just once even if Pointer occurs on multiple lines. If you want to insert it before each matching line add global flag:

ed -s file1 <<IN
g/Pointer/-r file2

Replace ,p with w if you want to edit the file in-place.

The accepted sed answer does work for most cases but if the marker is on the last line, the command won't work as expected: it will insert the content of File1 after the marker.
I have initially tried with:

sed '/Pointer/{r file1
N}' file2

which also works fine (as r will do its magic at the end of the cycle) but has the same problem if the marker is on the last line (there's no Next line after the last line). To work around that, you could add a newline to your input:

sed '/Pointer/{              # like the first one, but this time even if the
r file1                      # marker is on the last line in File2 it
N                            # will be on the second to last line in
}                            # the combined input so N will always work;
${                           # on the last line of input: if the line is
/^$/!{                       # not empty, it means the marker was on the last
s/\n$//                      # line in File2 so the final empty line in the
}                            # input was pulled i\n: remove the latter;
//d                          # if the line is empty, delete it
}' file2 <(printf %s\\n)

This will insert file2 content before each matching line. To insert it only before the first matching line you could use a loop and just pull in the next line until you get to end of file:

sed '/Pointer/{
r file2
}' file1 <(printf %s\\n)

With these sed solutions you lose the ability to edit in-place (but you can redirect to another file).

share|improve this answer

This is fairly simple with AWK:

File1 into File2 before pattern = "Pointer"

First load the contents of File1 into a variable


then do the insertion

awk -vf1="$f1" '/Pointer/{print f1;print;next}1' file2

(Or, if you want to insert File1 after "Pointer")

awk -vf1="$f1" '/Pointer/{print;print f1;next}1' file2
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.