4

Is there a way to use sed to substitute any string for any other string? Because sed uses a delimiter character for the find and replace expression, I can't figure out a way to write a sed command capable of substituting a string with potentially any character (or all characters) in any path for any other string (which may also contain any character).

Here is an example of what I have that does not work:

new_value="foobar"
old_value="baz"
echo "$some_path" | sed -e "s|$old_value|$new_value|"

This works unless $new_value or $old_value contains a pipe, in which case the command is invalid because the substitution syntax is broken by the variables used in the sed expression.

Is there a way to use sed to substitute any string for any other string?

If not, is there a Unix good alternative?

Stratus3D
  • 141
  • 4
  • 1
    [this link i believe is wot u want](https://www.google.co.in/url?sa=t&source=web&rct=j&url=https://unix.stackexchange.com/questions/129059/how-to-ensure-that-string-interpolated-into-sed-substitution-escapes-all-metac&ved=2ahUKEwiRt4ikyKvmAhWJyDgGHY48DLoQFjAAegQIBxAC&usg=AOvVaw3b1xrncc2_M71CEXm_m87j) – Rakesh Sharma Dec 10 '19 at 17:07
  • Thanks @RakeshSharma. You are right. That is what I need. The answers here are not correct. Do you recommend using `|` or `/` as the delimiter in the find and replace command? I figured `|` might be easier as paths will contain `/`. – Stratus3D Jan 01 '20 at 15:28

2 Answers2

4

A simple way around this is to escape everything in your variables before calling sed:

new_value="foo|bar"
old_value="ba|z"
new_value=$(printf '%q' "$new_value")
old_value=$(printf '%q' "$old_value")
some_path="/path/to/ba|z/file"

And then:

$ echo "$some_path" | sed -e "s|$old_value|$new_value|"
/path/to/foo|bar/file

The trick here is the printf '%q'. From help printf (showing the help of bash's builtin printf):

  %q    quote the argument in a way that can be reused as shell input
terdon
  • 234,489
  • 66
  • 447
  • 667
1

you can use shell paramater substitution to escape the needed char:

sed -e "s|${old_value//|/\\|}|${new_value//|/\\|}|"
glenn jackman
  • 84,176
  • 15
  • 116
  • 168