Bash pass variable as argument with quotes
I don't know where you got program
from, but it appears that it's broken. Here's a correct way to write it in bash:
#!/bin/bash
for arg in "$@"; do
echo "$arg"
done
This will print each argument in a separate line to make them easier to distinguish (it will of course have a problem with arguments that contain a line break, but we will not pass such an argument).
After you have saved the above as program
and gave it the execute permission, try this:
$ args='"Hello there"'
$ ./program "${args}"
"Hello there"
whereas
$ args='"Hello there"'
$ ./program ${args}
"Hello
there"
How to quotes in bash function parameters?
The reason this happens is because bash interprets the arguments, as you thought. The quotes simply aren't there any more when it calls the function, so this isn't possible. It worked in DOS because programs could interpret the command line themselves, not that it helps you!
How do I pass on script arguments that contain quotes/spaces?
Use "$@"
with quotes:
prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"
This will pass each argument exactly as it was received. If you don't include the quotes, each element will be split according to $IFS
:
"$@"
is like"$1" "$2" "$3" ...
, passing each element as a separate argument."$*"
is like"$1 $2 $3 ..."
, passing all elements concatenated as a single argument$*
and$@
is like$1 $2 $3 ...
, breaking up each element on whitespace, expanding all globs, and passing each resulting word as a separate element ($IFS
).
The same is true for arrays, such as "${array[@]}"
and "${array[*]}"
how to pass variable value with double quote in shell script
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 preserve quotes in printing a bash script's arguments
The quotes are removed before the arguments are passed to your script, so it's too late to preserve them. What you can do is preserve their effect when passing the arguments to the inner command, and reconstruct an equivalent quoted/escaped version of the arguments for printing.
For passing the arguments to the inner command "$@"
-- with the double-quotes, $@ preserves the original word breaks, meaning that the inner command receives exactly the same argument list that your script did.
For printing, you can use the %q format in bash's printf command to reconstruct the quoting. Note that this won't always reconstruct the original quoting, but will construct an equivalent quoted/escaped string. For example, if you passed the argument 'uptime ; uname -a'
it might print uptime\ \;\ uname\ -a
or "uptime ; uname -a"
or any other equivalent (see @William Pursell's answer for similar examples).
Here's an example of using these:
printf "Running command:"
printf " %q" innercmd "$@" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "$@"
If you have bash version 4.4 or later, you can use the @Q
modifier on parameter expansions to add quoting. This tends to prefer using single-quotes (as opposed to printf %q
's preference for escapes). You can combine this with $*
to get a reasonable result:
echo "Running command: innercmd ${*@Q}"
innercmd "$@"
Note that $*
mashes all arguments together into a single string with whitespace between them, which is normally not useful, but in this case each argument is individually quoted so the result is actually what you (probably) want. (Well, unless you changed IFS
, in which case the "whitespace" between arguments will be the first character of $IFS
, which may not be what you want.)
bash: How to warp interpolated variable in quotes to pass it (together with quotes) as argument to another command in script
The argument that the docker
binary sees will contain only the double quotes.
The single quotes are added by the set -x
mechanism only for the purpose of showing you what is in the argument list.
I suspect you don't actually want docker
to see any of the quotes. In that case, don't escape them in your command, and instead do
docker run -e "$env" some_image
Double quotes in that position means that if the value of $env
contains spaces, it will still be passed to docker
as a single argument (with spaces in it), rather than being split into several argument (which would confuse it).
These two commands will produce exactly the same argument array in the new process:
docker run -e VAR=val some_image
docker run -e "VAR=val" some_image
In the second of these cases the double quotes are interpreted by the shell (even though they are not necessary because the argument doesn't contain spaces), and what docker
sees in both cases is just the string VAR=val
.
If you try something like
env="VAR=multiple words"
set +x
docker run -r "$env" some_image
the third command-line argument to docker
will be the spaceful string VAR=multiple words
, and this get printed by set -x
as something like
+ docker run -r 'VAR=multiple words' some_image
because the print-the-command-line-before-executing code can see it would be confusing not to quote this spaceful string. Again the docker
command doesn't see any quotes at all in this invocation.
For debugging these things it can be useful to replace the actual command you're starting with echo
. This will print the raw arguments the command sees, without adding any quoting of its own. The downside of this is that you won't be able to tell the difference between a space that is part of a single argument and the space that echo
prints by itself between the arguments.
Related Topics
How to Check for Opencv on Ubuntu 9.10
Remove Empty Lines in a Text File via Grep
Why Disabling Interrupts Disables Kernel Preemption and How Spin Lock Disables Preemption
How to Deploy a Container into a Specific Node in a Docker Swarm
Finding Human-Readable Files on Unix
How to Output Return Code in Shell
Difference Between Virtual Page and Page Frame
Distributing Binary Applications Across Linux Distros
Save and Restore Terminal Content
How to Merge Images in Command Line
When Setting Ifs to Split on Newlines, Why Is It Necessary to Include a Backspace
No Local Gulp Install Found Even After Installing Npm Install -G Gulp
Linux-Based Firmware, How to Implement a Good Way to Update
Access Permissions of /Dev/Mem