Many people know how to use basic sed:
sed 's/hello/bonjour/' greetings.txt
echo "hi there" | sed 's/hi/hello/'
That’ll cover 80% of your sed
usage. This post is about the other 20%. Think
of it as a followup course after sed
101.
So you can change streams by piping output to sed
. What if you want to change
the file in-place?
Replacing in-place
sed
ships with the -i
flag. Let’s consult man sed
:
-i extension
Edit files in-place, saving backups with the specified extension.
Let’s try it:
$ ls
greetings.txt
$ cat greetings.txt
hello
hi there
$ sed -i .bak 's/hello/bonjour/' greetings.txt
$ ls
greetings.txt
greetings.txt.bak
$ cat greetings.txt
bonjour
hi there
$ cat greetings.txt.bak
hello
hi there
Note that on Linux systems, a space after -i
might cause an error, so instead
of -i .bak
, you can try -i.bak
.
So the original file contents are saved in a new file called [file_name].bak
,
and the new, changed version is in the original greetings.txt
. Now all we have
to do is:
rm greetings.txt.bak
And we’ve changed the file in-place. You are now the toast of the office, sung of by bards.
Let’s get l33t
Wait, there’s more in that man
entry for sed -i
:
If a zero-length extension is given, no backup will be saved. It is not
recommended to give a zero-length extension when in-place editing files, as
you risk corruption or partial content in situations where disk space is
exhausted, etc.
Zero-length extension, eh? Let’s use our original greetings.txt
file before
we changed it:
$ sed -i '' 's/hello/bonjour/' greetings.txt
$ ls
greetings.txt
$ cat greetings.txt
bonjour
hi there
$ cat greetings.txt.bak
cat: greetings.txt.bak: No such file or directory
The -i ''
(or, in Linux, just -i
) tells sed
to use a zero-length
extension for the backup. A zero-length extension means that the backup has the
same name as the new file, so no new file is created. It removes the need to run
rm
after doing an in-place replace.
I haven’t run into any disk-space problems with -i ''
. If you are worried
about the man
page’s warning, you can use the -i .bak
technique I mention in
the previous section.
Find and replace in multiple files
We like sed
so much that we use it in our replace
script. It
works like this:
replace foo bar **/*.rb
The first argument is the string we’re finding. The second is the string with which we’re replacing. The third is a pattern matching the list of files within which we want to restrict our search.
Now that you’re a sed
master, you’ll love reading replace
‘s source
code.
What’s next
If you found this useful, you might also enjoy the Grymoire sed guide. It’s helpful when learning and as a reference.