0

I am trying to modify a config file demo.cfg from a .sh file. I can modify it using sed, but the problem is when the value contains slash character.

For that I am using this code:

read -r -p "(Default PATH: /my/default/path/): " response
    case $response in
        (*[![:blank:]]*) sed -i '/key_one/s/= ''.*/= '$response'/' demo.cfg; echo 'OK';;
        (*) echo 'Using default path'
    esac

Here the error when the variable $response has slash:

sed: -e expression #1, char 20: unknown option to "s"

Could I scape this variable to use with sed function?

Here demo.cfg file

[params]
key_one = 1
key_two = 9
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
oscarvady
  • 450
  • 1
  • 4
  • 12

3 Answers3

1

Try passing response like this

${response//\//\\/}

This replaces all / with \/. Example:

$ response=/my/path/to/target
$ echo ${response//\//\\/}
\/my\/path\/to\/target

There is also an issue with your case statement. Your bash script should look like this:

#!/bin/bash

read -r -p "(Default PATH: /my/default/path/): " response
    case $response in
        *[![:blank:]]*) sed -i "/key_one/s/= .*/= ${response//\//\\/}/" demo.cfg
                echo 'OK'
                ;;
        *) echo 'Using default path'
                ;;
        esac
  • I am using this: `echo $response; sed -i '/key_one/s/= ''.*/= 'echo ${response//\//\\/}'/' demo.cfg;` but it fails: `Bad substitution` – oscarvady Jul 04 '16 at 13:00
  • The `echo` was only meant to demonstrate the behavior in bash. You do not need the `echo` inside the script. Just `${response//\//\\/}` will suffice. –  Jul 04 '16 at 13:02
  • @oscarvady There is also an issue with your `case` statement. I updated your script. –  Jul 04 '16 at 13:19
  • It fails again at sed line: `Bad substitution` :( – oscarvady Jul 04 '16 at 13:23
  • @oscarvady Did you copy/paste my updated script? Which version of bash are you using? It works in my bash 4.3.42. –  Jul 04 '16 at 13:24
  • Yes, it works now. I was using `#!/bin/sh` instead of `#!/bin/bash`. Could I execute this script as `sh`? Thanks again – oscarvady Jul 04 '16 at 13:29
  • @oscarvady `sh` normally behaves differently than `bash`, even if `/bin/sh` points to `bash`. See this thread for more info on this issue: http://stackoverflow.com/questions/26717870/why-does-bin-sh-behave-differently-to-bin-bash-even-if-one-points-to-the-other –  Jul 04 '16 at 13:34
0

You have two options:

  • Use a different separator for substitution, e.g. # or _:

    sed 's#/foo/bar/#/spam/egg#' file.txt
    

    Here use something that is not present in the pattern for clarity..

  • Or escape the actual /:

    sed 's/\/foo\/bar\//\/spam\/egg/' file.txt
    

    this is not cleanly readable, hence not recommended.

heemayl
  • 39,294
  • 7
  • 70
  • 76
0

To escape your chosen delimiter, use parameter expansion:

$ response=/foo/bar
$ response=${response//\//\\\/}
$ echo "$response"
chepner
  • 497,756
  • 71
  • 530
  • 681