Take the 2-minute tour ×
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.

I created two files:

echo -e "1\n2\n3\n4\n5" > 123.txt
echo -e "a\nb\nc\nd\ne" > abc.txt

I want to get the file 123.txt with the following contents:

1
2
3
b
c
d
4
5

So in other words insert the rows with numbers from 2 to 4 of the file abc.txt into the file 123.txt after the third line.

I have reviewed the many similar questions here, but did not find a suitable answer. Nevertheless I got the lines:

sed -n '2,4p' abc.txt

and put some text into the file after the third line:

sed -i '3a\mytext' 123.txt

How to do this using the previous command stdout or/and a sed/awk single command?

share|improve this question
    
Not an elegant solution. But still can be done as a single command. head -n +3 123.txt > tmp && cat abc.txt >> tmp && tail -n +2 123.txt >> tmp && mv tmp 123.txt –  Ramesh Jul 8 at 16:12
    
@Ramesh I agree with you. Only corrected your command because it gives the wrong result. head -3 123.txt > tmp && tail -4 abc.txt | head -3 >> tmp && tail -2 123.txt >> tmp && mv tmp 123.txt –  Apostle Jul 9 at 8:25

4 Answers 4

If your system has the GNU version of sed, you can use the GNU extension r command:

r filename
    As a GNU extension, this command accepts two addresses.

    Queue the contents of filename to be read and inserted into the
    output stream at the end of the current cycle, or when the next input 
    line is read. Note that if filename cannot be read, it is treated as 
    if it were an empty file, without any error indication.

    As a GNU sed extension, the special value /dev/stdin is supported for 
    the file name, which reads the contents of the standard input. 

For example,

$ sed '3r /dev/stdin' 123.txt < <(sed -n '2,4p' abc.txt)
1
2
3
b
c
d
4
5
share|improve this answer
2  
The r command is in POSIX. The only thing that isn't POSIX (but is common even on non-GNU systems) in the sed part is /dev/stdin. If you use a pipe instead of a command substitution, your shell snippet is POSIX apart from the requirement that /dev/stdin exist. –  Gilles Jul 8 at 22:04
    
The answer command gives the desired result on FreeBSD (a non-GNU system) as well. –  Apostle Jul 9 at 7:55

By using awk and sed:

$ awk 'FNR==3{print;system("sed -n '2,4p' abc.txt");next}1' 123.txt 
1
2
3
b
c
d
4
5
share|improve this answer

With sed, you can use the r command to insert a whole file. To insert a part of a file, extract that part and pipe it as input to sed. You can use sed to do the extraction as well.

sed -n '2,4p' abc.txt | sed -i '3r /dev/stdin' 123.txt

With awk, you can read one file and switch to another file in the middle.

awk <123.txt >123.txt.new '
    1                                    # print the input line
    NR==3 {                              # after line 3 of 123.txt, …
        while (getline < "abc.txt") {
            ++inner_NR;
            if (inner_NR >= 2) print;    # start printing at line 2 from abc.txt
            if (inner_NR == 4) break;    # stop after line 4
        }
    }
' &&
mv 123.txt.new 123.txt

You can also use head and tail to extract the parts of the files that you want to combine.

head -n 3 <123.txt >123.txt.new &&
<abc.txt tail -n +2 | head -n 3 >>123.txt.new &&
tail -n +4 123.txt >>123.txt.new &&
mv 123.txt.new 123.txt

You can combine the head+tail approach with sed. For huge files, this is likely to be the fastest.

<abc.txt tail -n +2 | head -n 3 | sed -i '3r /dev/stdin' 123.txt

Note that all these approaches write to a temporary file which is moved to 123.txt (even the approaches using sed -i, because that's what sed -i does under the hood).

share|improve this answer

In-place editing usinged and sed (on the bash prompt):

ed -s 123.txt<<<$'3r !sed -n "2,4p" abc.txt\nw'
share|improve this answer

Your Answer

 
discard

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.