How to insert a line in the middle of a file, with awk, given a search pattern to insert AFTER or BEFORE

awk

I want to insert some text in the middle of a file. The text to insert would be after a specific line, say, "<begin>". I don't know the line number, nor do I know the number of lines in the text to insert. I only know that after the line that reads "<begin>" I need to insert the content of another file.

I just don't know how to use awk to do something like this.

Thanks 🙂

Best Answer

Create a file with the following code. You could save it as:
insertfile.awk (or whatever you wish)

    BEGIN{
        while ( (getline < outerfile) > 0 )
        {
            if ($0 == matchline) 
            {  
                if ("after" == includematch)
                {
                    print
                }
                if ("before" == includematch)
                {
                    holdline = $0
                }
                  while ( (getline < innerfile) > 0) 
                {
                    print
                }
                close(innerfile)
                if ("before" == includematch)
                {
                     print holdline
                     holdline = ""
                }
            }
            else
            {
                print
            }
        }
        close(outerfile)
    }

The awk command line parameters used are:

-v outerfile="file1.txt"    This is the name of the file you are searching (and printing).
-v innerfile="file2.txt"    This is the name of the file you will insert when you file a match
-v matchline="Search Text"  This is what you will search for as a line in file1.txt
-v includematch="before"    Optional: insert the file, before the matchline
-v includematch="after"     Optional: insert the file, after the matchline
-v includematch=""          If "includematch" is any other value, or empty, or not present, 
                            then insert the file, REPLACING matchline.
-f "insertfile.awk"         This is the name of the awk command file.

Then, to use it you call awk like this:

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="cat" -f "insertfile.awk"  
(Read and print "file1.txt".  Search for line containing only "cat". REPLACE "cat" lines with "file2.txt"  

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="dog" -v includematch="before" -f "insertfile.awk"
(Read and print "file1.txt".  Search for line containing only "dog". Insert "file2.txt" Before matched line.

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="bird" -v includematch="after" -f "insertfile.awk"
(Read and print "file1.txt".  Search for line containing only "bird". Insert "file2.txt" After matched line.

In the awk script, you can edit it like this:

Change $0 to $1 or $2 or other to match a specific word instead of the whole line.  
"hard-code" the file-names instead of outerfile and innerfile if you wish.

If you want to "pipe" the input data into the script instead of getting it from a file, edit the insertfile.awk script like this:

        {
            if ($0 == matchline) 
            {

                if ("after" == includematch)
                {
                    print
                }
                if ("before" == includematch)
                {
                    holdline = $0
                }

                while ( (getline < innerfile) > 0) 
                {
                    print
                }
                close(innerfile)

                if ("before" == includematch)
                {
                     print holdline
                     holdline = ""
                }

            }
            else
            {
                print
            }
            close(outerfile)
        }

Then, to use it you call awk like this:

type "somefile.txt" | awk -v innerfile="file2.txt" -v matchline="cat" -f "insertfile.awk"  
(Read and print STDIN.  Search for line containing only "cat". REPLACE "cat" lines with "file2.txt"  

type "anyfile.txt" | awk -v innerfile="file2.txt" -v matchline="dog" -v includematch="before" -f "insertfile.awk"
(Read and print STDIN.  Search for line containg only "dog". Insert "file2.txt" Before matched line.

type "otherfile.txt" | awk -v innerfile="file2.txt" -v matchline="bird" -v includematch="after" -f "insertfile.awk"
(Read and print STDIN.  Search for line containg only "bird". Insert "file2.txt" After matched line.
Related Question