1

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
Heiko
  • 261
  • 3
  • 9

2 Answers2

7

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
Heiko
  • 261
  • 3
  • 9
1

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.)