Using multiple layers of quotes in bash
Normally, you could escape the inner quotes with \
:
RANGE="-H \"Range: bytes=20-30\""
But this won't work when running a command – unless you put eval
before the whole thing:
RANGE="-H \"Range: bytes=20-30\""
eval $CLIENT $REQ_HDRS $RSP_HDRS $RANGE
However, since you're using bash, not sh, you can put separate arguments in arrays:
RANGE=(-H "Range: bytes=20-30")
$CLIENT $REQ_HDRS $RSP_HDRS "${RANGE[@]}"
This can be extended to:
ARGS=(
-U # Request headers
-e # Response headers
-H "Range: bytes=20-30" # Range
)
$CLIENT "${ARGS[@]}"
bash dealing with multiple quotation
You can use here-doc to avoid quoting issues :
ssh node1 << 'EOF'
free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
EOF
Notice quotes around EOF so as to pass content as is.
We don't usually use -t
of ssh if we just run commands directly
Escaping multiple layers of mixed quotes for a curl command executed inside a bash script
First, as I said in a comment, storing commands in variables just doesn't work right. Variables are for data, not executable code. Second, you have two levels of quoting here: quotes that're part of the shell syntax (which are parsed, applied, and removed by the shell before the arguments are passed to `curl), and quotes that're part of the JSON syntax.
But the second problem is actually worse than that, because simply embedding an arbitrary string into some JSON may result in JSON syntax errors if the string contains characters that're part of JSON syntax. Which passwords are likely to do. To get the password (and username for that matter) embedded correctly in your JSON, use a tool that understands JSON syntax, like jq
:
userinfo=$(jq -n -c --arg u "$username" --arg p "$password" '{"username":$u,"password":$p}')
Explanation: this uses --arg
to set the jq
variables u
and p
to the shell variables $username
and $password
respectively (and the double-quotes around the shell variables will keep the shell from doing anything silly to the values), and creates a JSON snippet with them embedded. jq
will automatically add appropriate quoting/escaping/whatever is needed.
Then, to use it with curl
, use something like this:
resp=$(curl -k -i -H "Content-Type: application/json" -X POST -d "$userinfo" https://somerepo.example.com/flimflam)
Again, the double-quotes around $userinfo
keep the shell from doing anything silly. You should almost always put double-quotes around variables references in the shell.
Note that I never used the req
variable to store the command. If you need to print the command (or its equivalent), use something like this:
printf '%q ' curl -k -i -H "Content-Type: application/json" -X POST -d "$userinfo" https://somerepo.example.com/flimflam
echo
The %q
format specifier tells the shell to add appropriate quoting/escaping so that you could run the result as a shell command, and it'd work properly. (And the echo
is there because printf
doesn't automatically add a newline at the end of its output.)
two layers of quotes around a bash variable
echo "loadings_file <- '$loadings' ; calls_file <- '$file'"
If you specifically need double quoting:
echo "loadings_file <- \"$loadings\" ; calls_file <- \"$file\""
Triple nested quotations in shell script
Here is an example. caller.sh
uses gnome-terminal
to execute foo.sh
, which in turn prints all the arguments and then calls rsync
with the first argument.
caller.sh:
#!/bin/bash
gnome-terminal -t "TEST" -e "./foo.sh 'long path' arg2 arg3"
foo.sh:
#!/bin/bash
echo $# arguments
for i; do # same as: for i in "$@"; do
echo "$i"
done
rsync "$1" "some other path"
Edit: If $1
contains several parameters to rsync, some of which are long paths, the above won't work, since bash either passes "$1"
as one parameter, or $1
as multiple parameters, splitting it without regard to contained quotes.
There is (at least) one workaround, you can trick bash as follows:
caller2.sh:
#!/bin/bash
gnome-terminal -t "TEST" -e "./foo.sh '--option1 --option2 \"long path\"' arg2 arg3"
foo2.sh:
#!/bin/bash
rsync_command="rsync $1"
eval "$rsync_command"
This will do the equivalent of typing rsync --option1 --option2 "long path"
on the command line.
WARNING: This hack introduces a security vulnerability, $1
can be crafted to execute multiple commands if the user has any influence whatsoever over the string content (e.g. '--option1 --option2 \"long path\"; echo YOU HAVE BEEN OWNED'
will run rsync
and then execute the echo
command).
Bash Script single quotes inside of double quotes inside of single quotes
You don't need the bash -c
layer; just run ssh
itself directly from sudo
.
sudo -H -u user1 ssh -I /home/user1/.ssh/id_rsa -f user2@machine1.domain1.com "find ./ -name \"*.txt\""
(The -I
option should be unnecessary; if ssh
is run as user1
, then the default key is ~user1/.ssh/id_rsa
. You may have meant -i
anyway; -I
specifies a PKCS#11 library to use, not a private key.)
That said, you cannot include single quotes inside a single-quoted string. When in doubt, use double quotes, and properly escape any nested double quotes.
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 '
:
'
End first quotation which uses single quotes."
Start second quotation, using double-quotes.'
Quoted character."
End second quotation, using double-quotes.'
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.
Related Topics
Automate Scp with Multiple Files with Expect Script
Sharing Stdout Among Multiple Threads/Processes
Unix Unzip: How to Batch Unzip Zip Files in a Folder and Save in Subfolders
Create/Delete Users from Text File Using Bash Script
Find Out The Time Since Unix Epoch for a Certain Date Time
Does Each Unix File Description Have Its Own Read/Write Buffers
Convert Charset from a Entire Project to Utf-8
Linux - Create Animated Gif with Pan and Zoom
What Are The Lowest Possible Permissions for Typo3
Diff Files Comparing Only First N Characters of Each Line
Elastic Beanstalk: Log Task Customization on Amazon Linux 2 Platforms