17.7.4 Enabling In-Place File Editing

The inplace extension emulates GNU sed’s -i option, which performs “in-place” editing of each input file. Like GNU sed, the inplace extension replaces links (both hard and symbolic) with new files. If you wish to affect the target, you must dereference it first, for example using realpath from GNU Coreutils. It uses the bundled inplace.awk include file to invoke the extension properly. This extension makes use of the namespace facility to place all the variables and functions in the inplace namespace (see Namespaces in gawk):

# inplace --- load and invoke the inplace extension.

@load "inplace"

# Please set inplace::suffix to make a backup copy.  For example, you may
# want to set inplace::suffix to .bak on the command line or in a BEGIN rule.

# Before there were namespaces in gawk, this extension used
# INPLACE_SUFFIX as the variable for making backup copies. We allow this
# too, so that any code that used the previous version continues to work.

# By default, each filename on the command line will be edited inplace.
# But you can selectively disable this by adding an inplace::enable=0 argument
# prior to files that you do not want to process this way.  You can then
# reenable it later on the commandline by putting inplace::enable=1 before files
# that you wish to be subject to inplace editing.

# N.B. We call inplace::end() in the BEGINFILE and END rules so that any
# actions in an ENDFILE rule will be redirected as expected.

@namespace "inplace"

BEGIN {
    enable = 1         # enabled by default
}

BEGINFILE {
    sfx = (suffix ? suffix : awk::INPLACE_SUFFIX)
    if (filename != "")
        end(filename, sfx)
    if (enable)
        begin(filename = FILENAME, sfx)
    else
        filename = ""
}

END {
    if (filename != "")
        end(filename, (suffix ? suffix : awk::INPLACE_SUFFIX))
}

For each regular file that is processed, the extension redirects standard output to a temporary file configured to have the same owner and permissions as the original. After the file has been processed, the extension restores standard output to its original destination. (Due to this implementation, it helps to redirect gawk’s standard output to /dev/null, instead of leaving it set to your terminal, so that output will be block-buffered instead of line-buffered.)

If inplace::suffix is not an empty string, the original file is linked to a backup file name created by appending that suffix. Finally, the temporary file is renamed to the original file name.

Note that the use of this feature can be controlled by placing ‘inplace::enable=0’ on the command-line prior to listing files that should not be processed this way. You can reenable inplace editing by adding an ‘inplace::enable=1’ argument prior to files that should be subject to inplace editing.

The inplace::filename variable serves to keep track of the current file name so as to not invoke inplace::end() before processing the first file.

If any error occurs, the extension issues a fatal error to terminate processing immediately without damaging the original file.

Here are some simple examples:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3

To keep a backup copy of the original files, try this:

$ gawk -i inplace -v inplace::suffix=.bak '{ gsub(/foo/, "bar") }
> { print }' file1 file2 file3

Please note that, while the extension does attempt to preserve ownership and permissions, it makes no attempt to copy the ACLs from the original file.

If the program dies prematurely, as might happen if an unhandled signal is received, a temporary file may be left behind.