Use variable inside double quotes inside single quotes in sed [duplicate] - bash

This question already has answers here:
sed substitution with Bash variables
(6 answers)
Closed 8 years ago.
I want to search for a string enclosed in double quotes given by a positional parameter. This is what I've done:
#!/bin/bash
FOO=$0
sed -i 's/"${FOO}"/bar/m' file.txt
Neither "$FOO" nor \"a${FOO}\"/ work.
I am aware that for variables to be expanded, you have to enclose the whole regex in double quotes (sed substitution with bash variables). The thing is that the string I am searching for is also enclosed in double quotes, that is why I enclosed the whole regex in single quotes. I also tried to enclose it in double quotes and escaping the double quotes, but it didn't work.
An explanation of the logic behind single and double quotes escaping would be really useful.

Use double quotes to quote the sed commands as
sed -i "s/\"${FOO}\"/bar/m" file.txt
Test:
$ echo $b
hello
$ echo \"hello\" | sed "s/\"$b\"/asdf/"
asdf

Related

how to pass variable value with double quote in shell script [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 1 year ago.
USER_UID=$1
echo 'generate_token("$USER_UID")'
I want output like
generate_token("1234567")
i tried multiple ways but didn't worked. it just print same line without value generate_jwt("$USER_UID")
When you use single quotes, it causes the shell to preserve the literal value of each character within the quotes. This means the $ will be treated as a literal $ character.
You should use double quotes:
USER_UID="$1"
echo "generate_token(\"$USER_UID\")"
From the bash man page, under the Quoting section:
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !.
For POSIX details on quoting, see here.
Example in an interactive shell:
$ USER_UID='foo'
$ echo "generate_token(\"$USER_UID\")"
generate_token("foo")
This will also work if USER_UID contains spaces:
$ USER_UID='var with spaces'
$ echo "generate_token(\"$USER_UID\")"
generate_token("var with spaces")

How can I escape double quotes in Bash? [duplicate]

This question already has answers here:
How can I escape a double quote inside double quotes?
(9 answers)
Closed 4 years ago.
I want to escape double quotes in Bash. I followed the following approach:
#!/bin/bash
this is a \"number\"!
But is there another way?
You can enclose the double quotes in single quotes:
echo '"'hola'"'
Or alternatively the whole text, including the double quotes:
echo '"hola"'
With GNU Bash:
echo -e "this is a \x22number\x22"
Output:
this is a "number"

Path substitution with sed and shell variables on OS X

I am on Mac OS X and using sed for an in-place replacement.
Essentially I have this:
#!/bin/sh -e
PREFIX="$1"
sed -i bak -e 's|OCAMLDIR|"${PREFIX}"|g' ocamloptrev
Where PREFIX is a path, hence I'm using the |.
Unfortunately, the variable in the file path is not getting evaluated as I expected, I end up with:
OCAMLC="${PREFIX}"/bin/ocamlopt
How can I get the right evaluation of ${PREFIX} into the sed command?
Try this:
#!/bin/sh -e
PREFIX="$1"
sed -i bak -e 's|OCAMLDIR|'"${PREFIX}"'|g' ocamloptrev
What you're basically doing, is "exiting"/getting outside the single-quoted string, entering into a double-quoted string, interpreting the variable inside double-quotes, and then entering the single quotes again.
With this simple example, we could also just use double-quotes, which allow variables to be interpreted:
#!/bin/sh -e
PREFIX="$1"
sed -i bak -e "s|OCAMLDIR|${PREFIX}|g" ocamloptrev
If you try to use double-quotes ("") inside single-quotes, they don't get interpreted either. This part of the Bash manual explains this in more detail.
3.1.2.2 Single Quotes
Enclosing characters in single quotes (‘'’) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
3.1.2.3 Double Quotes
Enclosing characters in double quotes (‘"’) preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes (see Shell Expansions). ...
Shell variables are not expanded inside single quotes (there are no metacharacters within single quotes, not even backslashes), so you need to use something like this, with the double quotes around ${PREFIX} ensuring that spaces etc in the value are handled correctly:
sed -i bak -e 's|OCAMLDIR|'"${PREFIX}"'|g' ocamloptrev
Or you could even use:
sed -i bak -e "s|OCAMLDIR|${PREFIX}|g" ocamloptrev
The latter is safe because the material inside the double quotes does not contain shell metacharacters (dollar signs, backslashes and back-quotes are the main danger signs). If there were dodgy characters in the rest of the string, the first version is safer to use.
Personally, I'd use .bak rather than just bak as the suffix.

Expand variables in sed

I need use sed into bash script, for add lines after any line numer of script with some pair of values (below work)
sed -i.bak '14i\some_text=some_text' file
But I need on script bash (sh) for expand variables (below not work)
sed -i.bak '$number_linei\$var1=$var2' $var3
Just use double quotes instead of single quotes. You'll also need to use {} to delimit the number_line variable correctly and escape the \, too.
sed -i.bak "${number_line}i\\$var1=$var2" $var3
I'd personally prefer to see all of the variables use the {}, ending up with something like:
sed -i.bak "${number_line}i\\${var1}=${var2}" ${var3}
Change single quotes to double quotes:
man bash:
Enclosing characters in single quotes preserves the literal value of
each character within the quotes.
Enclosing characters in double quotes preserves the literal value of
all characters within the quotes, with the exception of $, `, \, and,
when history expansion is enabled, !. The characters $ and ` retain
their special meaning within double quotes.

Use a variable's value in a sed command [duplicate]

This question already has answers here:
Environment variable substitution in sed
(12 answers)
sed substitution with Bash variables
(6 answers)
Closed 10 months ago.
I can't seem to use a variable in a sed command, for example:
sed "24s/.*/"$ct_tname"/" file1.sas > file2.sas
I want $ct_tname the variable, not literally $ct_tname, which is what I keep getting.
Anybody know how to get this to work?
The problem is actually more complex and I omitted some information.
ct_fname="%let outputfile="/user/ct_"$1".csv";"
Here, $1 is the argument passed in at the start of my bash script (sed is being run inside a bash script).
This doesn't run successfully, but it does run if I replace ct_fname with
ct_fname="%let table=ct_$1;"
Is there a way to get the first ct_fname to be passed successfully?
you need to use double quotes (") instead of single quotes (').
single quotes pass their content literally, without translating variables (expansion).
try
sed "24s/.*/\"$ct_tname\"/" file1.sas > file2.sas
btw, if you're going to be editing a file (that is if file2.sas is a temporary file), you should be using ed instead.
In my case, i just remplaced single quotes by the double ones:
for a in $(cat ext.cnf); do sed -n "/$a$/p" file1 >> file2; done
For now, it's working well...
The problem is that when $ct_fname is substituted, sed sees extra / separators, so
sed "24s/.*/"$ct_tname"/" file1.sas > file2.sas
becomes
sed "24s/.*/"%let outputfile=/user/ct_ARGUMENT1.csv;"/" file1.sas > file2.sas
and you'll get a sed error because there are 5 / instead of the expected 3.
Instead, change your sed separators to an unused character like | or :, and either single or double quotes will work just fine:
sed '24s|.*|'$ct_tname'|' file1.sas > file2.sas
sed "24s|.*|"$ct_tname"|" file1.sas > file2.sas
Shell variables are not expanded inside single quotes. Try this instead:
sed "24s/.*/\"$ct_tname\"/" file1.sas > file2.sas
You need to use double (") quotes, with single (') quotes the value of the variable doesn't get replaced. Since you have double quotes in your replacement text, you need to escape them:
sed "24s/.*/\"$ct_tname\"/" file1.sas > file2.sas
Other answers focus on the use of escaped double quotes in their examples. Note that this is not always what you want :
$ FOO="auie"; echo foo123bar|sed "s/123/\"$FOO\"/"
foo"auie"bar
$ FOO="auie"; echo foo123bar|sed "s/123/$FOO/"
fooauiebar
$ FOO="auie"; echo fooauiebar|sed "s/\"$FOO\"/123/"
fooauiebar
$ FOO="auie"; echo fooauiebar|sed "s/$FOO/123/"
foo123bar

Resources