The -i inplace
includes the built-in inplace.awk
include file to emulate sed -i
in-place editing but there are some caveats that come from the method used for this emulation.
Because it works by fiddling with the processing of each input file (by using the BEGINFILE
pattern), anything printed in the BEGIN
selector still goes to the start-up output stream rather than to the "fiddled" output stream. That's because the first input file has yet to begin processing at that point.
So what you'll see is first line
going to standard output then the two lines from the input file being printed in-place back to that file. You just may not have realised that last bit since you don't change the lines in the file when you write them back.
This was no doubt a difficult implementation decision for the creators of inplace.awk
since in-place editing over multiple files needs to be catered for. The question is: where should output go in BEGIN
for in-place editing?
You have a couple of options here.
First, if you know you'll only ever process one file, you can use the normal trick, with BEGIN
but without inplace
:
awk 'BEGIN {print "first line" } {print}' file.txt > /tmp/$$ && mv /tmp/$$ file.txt
Second, using inplace
but not BEGIN
, you need to first decide which of the input files it should affect. If you want it to affect all input files, that means something like:
awk -i inplace 'FNR==1 {print "first line";print;next} {print}' file1.txt file2.txt
If you want it to affect just the first input file, use NR
rather than FNR
(the former never decreases, the latter resets to one for each new input file).
Finally, for the case where all files should be affected, you can use the same method that inplace
itself uses.
As special patterns like BEGIN
are executed in order of definition (and -i
comes before processing of your script), simply use BEGINFILE
rather than BEGIN
, as per the following transcript:
=====
pax@styx:~$ cat xx.001
Original line from xx.001
=====
pax@styx:~$ cat xx.002
Original line from xx.002
=====
pax@styx:~$ cat xx.awk
BEGINFILE {
print "inserted line"
}
{
print
}
=====
pax@styx:~$ awk -i inplace -f xx.awk xx.001 xx.002
=====
pax@styx:~$ cat xx.001
inserted line
Original line from xx.001
=====
pax@styx:~$ cat xx.002
inserted line
Original line from xx.002
The BEGINFILE
from inplace
will first weave its magic to capture output (per input file), then your BEGINFILE
will print to that capture area.