Shouldn't the second 'test' line also get replaced? How would I have to write the command to replace all 'test'?
$ sed 's/test/toast/' texttest.txt
toast file test file hahahaha 1
toast file test file hahahaha 2
Ok, got it …
g Make the substitution for all non-overlapping matches of the regular expression, not just the first one.
$ sed 's/test/toast/g' texttest.txt
toast file toast file hahahaha 1
toast file toast file hahahaha 2
sed
.
– Hashim Aziz
Nov 29 '20 at 00:11
As you've already found out, s/test/toast/
will only replace the first occurrence of "test
" on each line with "toast
". To make sed replace all non-overlapping occurrences of "test
" with "toast
", you need to append the global replacement flag g
to the replacement command, as in:
$ echo 'This test is a test.' | sed 's/test/toast/g'
This toast is a toast.
Note that the g
flag only handles non-overlapping replacements, and will e.g. turn "testest
" into "toastest
", not into "toastoast
":
$ echo 'This test is the testest test.' | sed 's/test/toast/g'
This toast is the toastest toast.
If you do want overlapping replacements, this can be worked around using a loop:
$ echo 'This test is the testest test.' | sed ':loop; s/test/toast/; t loop'
This toast is the toastoast toast.
Ps. Using ;
as a command separator, as above, is a GNU sed feature. For BSD sed (as found e.g. on MacOS), you need to use literal newlines or multiple -e
arguments instead:
$ echo 'This test is the testest test.' | sed ':loop
s/test/toast/
t loop'
This toast is the toastoast toast.
$ echo 'This test is the testest test.' | sed $':loop\n s/test/toast/\n t loop'
This toast is the toastoast toast.
$ echo 'This test is the testest test.' | sed -e ':loop' -e 's/test/toast/' -e 't loop'
This toast is the toastoast toast.
(All of these will also work on GNU sed. The second version, with $''
, relies on a feature of some shells, such as bash and zsh, and may require quoting any backslashes appearing in your sed code itself.)