0

I have a FILE variable in bash which I want replace RT in FILE's value to TTT.

Operations:

FILE="BlazeRT 123"
source_dir=BlazeRT
target_dir=BlazeTTT
newfile="$(echo ${FILE} | sed -e \"s/${source_dir}/${target_dir}/g\")"

I got error:

sed: -e expression #1, char 1: unknown command: `"'

Seems the error occurs when shell eval echo ${FILE} | sed -e \"s/${source_dir}/${target_dir}/g\".

Now, I wanna know ho to correct the last command.

Thanks in advance!

  • Why escape the double quotes, just do sed -e "s/${source_dir}/${target_dir}/g"? – Inian Sep 24 '21 at 11:13
  • maybe newfile="${FILE/$source_dir/$target_dir}" – Bodo Sep 24 '21 at 11:31
  • @Bodo yes, it works. But for now, I wanna know is there a way to fix it? – roachsinai Sep 24 '21 at 11:40
  • @Inian I need use echo to get value of FILE and assignment it newfile. – roachsinai Sep 24 '21 at 11:41
  • @roachsinai Inian's comment already shows how to change your command. Compare it with the code in your question and look for similarities. To see how the shell processes your command, execute set -x before newfile=... (and set +x afterwards). – Bodo Sep 24 '21 at 11:48
  • @Bodo thanks for pointing that. So I don't need to escape double quotes just because there is () which let bash know the couple between those four "s? – roachsinai Sep 24 '21 at 11:51
  • I think so, but I didn't find a documentation. See also https://unix.stackexchange.com/q/118433/330217 – Bodo Sep 24 '21 at 12:43
  • @roachsinai See https://pubs.opengroup.org/onlinepubs/009604499/utilities/xcu_chap02.html#tag_02_06_03 "With the $( command) form, all characters following the open parenthesis to the matching closing parenthesis constitute the command. Any valid shell script can be used for command, except a script consisting solely of redirections which produces unspecified results." – Vilinkameni Sep 24 '21 at 13:50
  • But with the archaic form of command substitution with backticks, the backslashes would work differently, and more of them might be needed. (Maybe not in this particular case, but don't count on that.) See: Have backticks (i.e. cmd) in *sh shells been deprecated? and http://mywiki.wooledge.org/BashFAQ/082 for the – ilkkachu Sep 30 '21 at 20:24

1 Answers1

0

There are about four issues with the code that you are trying to run.

  • You are escaping the double-quote characters surrounding the sed expression. Doing so makes the double-quotes part of the expression that sed will try to run. Since there is no " command in sed, the utility complains about this, saying "unknown command". You can remedy this by simply not escaping the double-quotes.
  • You use $FILE unquoted. The shell would therefore split the value on characters in $IFS (space, tab, and newline by default) and perform filename generation (globbing) on the resulting words. You would correct this by double-quoting the $FILE expansion.
  • The echo utility would, under certain circumstances, modify the data that it outputs by expanding escape sequences like \t and \n if they occur in the string that it outputs. You should, therefore, only ever use echo on static strings if you want to be sure what it will output. In all other cases, use printf.
  • The sed command would fail if either $source_dir or $target_dir contained slashes since the slash is used as the delimiter for the s/// command in sed by default. Luckily, it is easy to use any other delimiter in that command, and you need to pick one that would never occur in your data. Unfortunately, you must avoid several other substrings and characters if you want sed to interpret the values as fixed strings rather than regular expressions. The second string, $target_string, may furthermore not contain substrings like \1, \2 or &.

It would be more efficient and safer to use a parameter substitution in the shell itself rather than trying to use sed in this instance. The bash shell can do things like ${variable//pattern/word} to replace all substrings matching the shell pattern pattern in $variable with word (use a single / in place of // to replace only the first occurrence).

newfile=${FILE/"$source_dir"/$target_dir}

We're double-quoting $source_dir to avoid using its value as a globbing pattern.

Kusalananda
  • 333,661