EbuVitae EbuVitae - 1 month ago 6
Bash Question

Copying the contents of a file into another file at a point relative to the end of the file

New to StackExchange, forgive me for errors.

I have an input file that needs to be copied into another file, before the last character.

 

inputfile.txt:

input {
"inputstuff"
}


filetowriteto.txt:

Stuff {
foo {
"foostuff"
}
bar {
"barstuff"
}
}


 

After running the script, the resulting file should now be:

filetowriteto.txt:

Stuff {
foo {
"foostuff"
}
bar {
"barstuff"
}
input {
"inputstuff"
}
}


 

Basically the script copies the
input
set of lines and pastes them just before the last right bracket in
filetowriteto.txt
.

The script can't rely on line counts, since
filetowriteto.txt
doesn't have a predicable amount of foo or bar lines, and I don't know how to use sed or awk to do this.

Answer

Try:

$ awk 'FNR==NR{ if (NR>1) print last; last=$0; next} {print "       " $0} END{print last}' filetowriteto.txt inputfile.txt 
Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
       input {
              "inputstuff"
       }
}

To change the file in place:

awk 'FNR==NR{ if (NR>1) print last; last=$0; next} {print "       " $0} END{print last}' filetowriteto.txt inputfile.txt >tmp && mv tmp filetowriteto.txt

How it works

  • FNR==NR{ if (NR>1) print last; last=$0; next}

    While reading the first file, (a) if we are not on the first line, print the value of last, (b) assign the text of the current line to last, and (c) skip the rest of the commands and jump to the next line.

    This uses a common awk trick. The condition FNR==NR is only true while we are reading the first file. This is because, in awk, NR is the number of lines that we have read so far while FNR is the number of lines that we have read so far from the current file. Thus, FNR==NR is only true when we are reading from the first file.

  • print " " $0

    While reading the second file, print each line with some leading white space.

  • END{print last}

    After we have finished printing the second file, print the last line of the first file.