Using POSIX sed for infile substitution
Something I learned when I started writing tools for developers in companies is
that there’s GNU sed
, BSD
sed
and that they are not
compatible for something that I tend to write a lot: infile substitution.
I would find myself doing conditionals, finding out if it was running in a
Darwin/BSD or if it was running on Linux. Then there was the bit where some
people would install gnu-sed
from Homebrew in their macs and add the gnubin
path to their $PATH
which then would break my conditionals because they would
be using GNU sed
in which I thought were BSD sed
.
This made really hard building scripts that would work both in all developers machines and deployment servers.
In goes POSIX
sed
. So
there’s a “standard” which not many people limits itself to use, because using
-i
is too convenient, which BSD and GNU both implement yet differently (one
requires -i ''
the other either -i
or -i''
so both implementations are
incompatible between themselves). But POSIX sed
only has -e
, -f
and -n
.
So easy, right? Let’s just do a sed
and pipe it out to the same file:
sed -e "s/foo/bar/" "filename" > "filename"
Done. Is it? No! If you check the content of the file it will be blank. So you need to create a temp file, modify it and then remove the temp file:
sed -e "s/foo/bar/" "filename" > "filename.tmp"
mv "filename.tmp" "filename"
So it’s basically your call to decide if you can write an extra line of code on
your scripts or write a whole logic to figure out what sed
is being used and
if it should be -i
or -i ''
.