Bash: Variable in Single Quote

Expansion of variables inside single quotes in a command in Bash

Inside single quotes everything is preserved literally, without exception.

That means you have to close the quotes, insert something, and then re-enter again.

'before'"$variable"'after'
'before'"'"'after'
'before'\''after'

Word concatenation is simply done by juxtaposition. As you can verify, each of the above lines is a single word to the shell. Quotes (single or double quotes, depending on the situation) don't isolate words. They are only used to disable interpretation of various special characters, like whitespace, $, ;... For a good tutorial on quoting see Mark Reed's answer. Also relevant: Which characters need to be escaped in bash?

Do not concatenate strings interpreted by a shell

You should absolutely avoid building shell commands by concatenating variables. This is a bad idea similar to concatenation of SQL fragments (SQL injection!).

Usually it is possible to have placeholders in the command, and to supply the command together with variables so that the callee can receive them from the invocation arguments list.

For example, the following is very unsafe. DON'T DO THIS

script="echo \"Argument 1 is: $myvar\""
/bin/sh -c "$script"

If the contents of $myvar is untrusted, here is an exploit:

myvar='foo"; echo "you were hacked'

Instead of the above invocation, use positional arguments. The following invocation is better -- it's not exploitable:

script='echo "arg 1 is: $1"'
/bin/sh -c "$script" -- "$myvar"

Note the use of single ticks in the assignment to script, which means that it's taken literally, without variable expansion or any other form of interpretation.

Difference between single and double quotes in Bash

Single quotes won't interpolate anything, but double quotes will. For example: variables, backticks, certain \ escapes, etc.

Example:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")

The Bash manual has this to say:

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). The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.

The special parameters * and @ have special meaning when in double quotes (see Shell Parameter Expansion).

How do I use variables in single quoted strings?

Variables are expanded in double quoted strings, but not in single quoted strings:

 $ name=World

$ echo "Hello $name"
Hello World

$ echo 'Hello $name'
Hello $name

If you can simply switch quotes, do so.

If you prefer sticking with single quotes to avoid the additional escaping, you can instead mix and match quotes in the same argument:

 $ echo 'single quoted. '"Double quoted. "'Single quoted again.'
single quoted. Double quoted. Single quoted again.

$ echo '"$name" has the value '"$name"
"$name" has the value World

Applied to your case:

 echo 'test text "here_is_some_test_text_'"$counter"'" "output"' >> "$FILE"

how to use the bash variable in single quotes

Variables don't expand in single quotes, which means that you simply have to ensure that they are not single-quoted. You have several possibilities, for instance:

'payload={"text": "failure with '"${VAR}"' failed for"}'

or

"payload={\"text\": \"failure with ${VAR} failed for\"}"

Bash: Variable in single quote

I'll add yet another option to the list: define a variable as newline, then use that inside double-quotes.

nl=$'\n'
...
--summary "Today is ${date}. Poor whiskers takes a tumble.${nl}She's fine, though, don't worry."

How to escape single quotes within single quoted strings

If you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
# ^^^^^ ^^^^^ ^^^^^ ^^^^
# 12345 12345 12345 1234

Explanation of how '"'"' is interpreted as just ':

  1. ' End first quotation which uses single quotes.
  2. " Start second quotation, using double-quotes.
  3. ' Quoted character.
  4. " End second quotation, using double-quotes.
  5. ' Start third quotation, using single quotes.

If you do not place any whitespaces between (1) and (2), or between (4) and (5), the shell will interpret that string as a one long word.

Single quotes around variable value

Like every other command the assignment of a value to a variable will be parsed by the shell, too. To prevent the shell from parsing the special characters must be "quoted". Single characters can be quoted with the backslash (\), multiple characters can be quoted with single quotes (') or double quotes ("). Within single quotes every character will be taken literally. Double-quoted characters will mostly taken literally, with the main exeption (among some others): variables will be replaced with their contents.

To assign the Value "JSBDbshe66!#12$@a" in the command line it must be single-quoted because of the bang (!) sign (see bash bang for further information):

:~$ DEV_ARM_CLIENT_SECRET='JSBDbshe66!#12$@a'

The command

:~$ echo $DEV_ARM_CLIENT_SECRET

gives you the desired output:

JSBDbshe66!#12$@a

To copy this value to another variable just enter in the command line:

ARM_CLIENT_SECRET=$DEV_ARM_CLIENT_SECRET

Alternatively you can enter:

ARM_CLIENT_SECRET="$DEV_ARM_CLIENT_SECRET"

to receive the same result. The variable-name between the double quotes will be replaced with the value and finally the shell removes the Quotes. If you put the variable name between single quotes

ARM_CLIENT_SECRET='$DEV_ARM_CLIENT_SECRET'

every character between the quotes will be taken literally:

:~$ echo $ARM_CLIENT_SECRET

$DEV_ARM_CLIENT_SECRET

If you quote the single quotes via Backslash

:~$ ARM_CLIENT_SECRET=\'$DEV_ARM_CLIENT_SECRET\'

the value of "$ARM_CLIENT_SECRET" will be the same as $DEV_ARM_CLIENT_SECRET with an additional leading and a trailing single quote:

:~$ echo $ARM_CLIENT_SECRET

'JSBDbshe66!#12$@a'

How do I expand a variable inside single quotes?

You could just use double quotes, escaping the ones inside the JSON string:

curl https://www.googleapis.com/urlshortener/v1/url?key=MyKey -H \\
'Content-Type: application/json' -d "{\"longUrl\": \"$1\"}"

How to echo variable inside single quotes using Bash?

JSON string values should be quoted and so should parameter expansions. You can achieve this by using double quotes around the entire JSON string and escaping the inner double quotes, like this:

curl -i -H "Content-Type: application/json" -X POST -d "{\"mountpoint\":\"$final\"}" http://127.0.0.1:5000/connect

As mentioned in the comments, a more robust approach would be to use a tool such as jq to generate the JSON:

json=$(jq -n --arg final "$final" '{ mountpoint: $final }')
curl -i -H "Content-Type: application/json" -X POST -d "$json" http://127.0.0.1:5000/connect


Related Topics



Leave a reply



Submit