This question already has answers here:
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
Closed 4 years ago.
I am attempting to do a curl command that uses a predefined variable as a header.
header='-H "Content-Type: application/json" -H "userGUID: 7feb6e62-35da-4def-88e9-376e788ffd97" -H "Content-Length: 51"'
And this is essentially the curl command
curl $header -w "http code: %{http_code}\\n" -X POST -d $BODY $URL
Which then returns the error message
rl: (6) Could not resolve host: application
curl: (6) Could not resolve host: 7feb6e62-35da-4def-88e9-376e788ffd97"
curl: (6) Could not resolve host: 51"
This works as expected
curl -H "Content-Type: application/json" -H "userGUID: 7feb6e62-35da-4def-88e9-376e788ffd97" -H "Content-Length: 51" -w "http code: %{http_code}\\n" -X POST -d $BODY $URL
The reason I'm trying to pass the header as a variable is because I'm writing a script that loops through and array, but currently this does not work with headers for some reason. There is no issue passing arguments for body.
Be aware that variable expansion in bash can catch people off guard easily.
A pretty good rule of thumb is to put double quotes around any variable you want to expand like curl "$header" -w "http code: %{http_code}\\n" -X POST -d "$BODY" "$URL".
Bash always expands $SOMETHING variables if they appear on their own, or if they appear in double quotes. (Not if they appear in single quotes).
When expanded with double quotes they are treated as a single "token" by the shell, no matter what.
When expanded without double quotes they will be parsed as if you had typed their contents instead of the variable. So - if that variable had spaces, that may mean the shell will treat those as separators between arguments.
Related
This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 3 years ago.
I have an argument to a bash script which could be a string with spaces. How can I use this within a string concatenation such as below:
#!/usr/bin/env bash
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"'$1'"}' https://hooks.slack.com/services/<rest of URL secret!>
From cmd line if I do:
$./myscript.sh oneword
It works perfectly fine. But if I pass a string with spaces:
$./myscript.sh "two words"
curl: (3) [globbing] unmatched close brace/bracket in column 5
invalid_payload%
I have tried all sorts of quoting to concatenate it correctly, but to no avail. Thanks
You need to quote $1 as well in your JSON payload:
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"'"$1"'"}' https://hooks.slack.com/services/<rest of URL secret!>
This question already has answers here:
Expansion of variables inside single quotes in a command in Bash
(8 answers)
Closed 3 years ago.
I am executing curl command inside bash script.
Issue is in curl command I have to pass some variables($summary,$description).
but as these variables are in single quote('), variables are not getting assigned.
FYI: I can't remove single quote and also can't replace with double quotes.
How can I overcome this situation.
Curl Command:
curl -X POST -d '{"summary": "$summary", "description": "$description", "moduleMapAssets": [{"name":"Rates | IRD"},{"name":"CRD | CRD"}]}' -H "Content-Type: application/json"
You can (and must) use double-quotes, you just need to escape the double-quotes that are part of the string:
curl -X POST -d "{\"summary\": \"$summary\", \"description\": \"$description\", \"moduleMapAssets\": [{\"name\":\"Rates | IRD\"},{\"name\":\"CRD | CRD\"}]}" -H "Content-Type: application/json"
As #MikeHolt pointed out in a comment, it's also possible to mix quoting styles within a single string, so you could switch back and forth between single-quoted sections that include literal double-quotes, and double-quoted sections that include variable references:
curl -X POST -d '{"summary": "'"$summary"'", "description": "'"$description"'", "moduleMapAssets": [{"name":"Rates | IRD"},{"name":"CRD | CRD"}]}' -H "Content-Type: application/json"
To explain that in a little more detail: ... '{"summary": "'"$summary"'", "description"...' is parsed as the single-quoted section '{"summary": "' (within which the double-quotes are literal), followed immediately by the double-quoted section "$summary" (within which the variable gets expanded), followed immediately by another single-quoted section '", "description"...' etc. Since there are no spaces between these sections, they're treated as one long argument to curl.
BTW, if any of your variables can contain double-quotes or backslashes themselves, things get much more complicated. If something like this is a possibility, you should be using something like jq to create the string. Something like this:
jsonstring=$(jq -n --arg summary "$summary" --arg description "$description" '{
summary: $summary,
description: $description,
moduleMapAssets: [{name: "Rates | IRD"}, {name: "CRD | CRD"}]
}' )
curl -X POST -d "$jsonstring" -H "Content-Type: application/json"
try use with backslash on sigle-quotes
curl -X POST -d \'{"summary": "$summary", "description": "$description", "moduleMapAssets": [{"name":"Rates | IRD"},{"name":"CRD | CRD"}]}\' -H "Content-Type: application/json"
This question already has answers here:
Command not found error in Bash variable assignment
(5 answers)
Closed 4 years ago.
i'm new to shelling in linux.
i'm trying to write a shell script that uses a REST method and creates some datasources on grafana
i need the url to be modular and to be taken from an argument.
this is the line i'm trying to run:
srv_url = "1.1.1.1:8080"
RESULT=$(/bin/curl --user admin:admin 'http://localhost:3000/api/datasources' -X POST -H 'Content-Type: application/json;charset=UTF-8' --data-binary '{"name":"Events","isDefault":false ,"type":"influxdb","url":"http://$srv_url","access":"proxy","basicAuth":false}')
as you can see i'm trying to plant the variable $srv_url inside ("url":"http://$srv_url"), but it will not take its value, whatever i tried the script uses its literal name, and not its value.
any ideas?
thanks.
Variable substitution in strings only works with double quotes, not single quotes. That means that you'll have to escape all of the quotes in the string or use single quotes:
srv_url = "1.1.1.1:8080"
RESULT=$(/bin/curl --user admin:admin 'http://localhost:3000/api/datasources' -X POST -H 'Content-Type: application/json;charset=UTF-8' --data-binary "{\"name\":\"Events\",\"isDefault\":false ,\"type\":\"influxdb\",\"url\":\"http://$srv_url\",\"access\":\"proxy\",\"basicAuth\":false}")
Alternatively, you could do something like this by ending the single quote string and wrapping the variable in double quotes:
RESULT=$(/bin/curl --user admin:admin 'http://localhost:3000/api/datasources' -X POST -H 'Content-Type: application/json;charset=UTF-8' --data-binary '{"name":"Events","isDefault":false ,"type":"influxdb","url":"http://'"$srv_url"'","access":"proxy","basicAuth":false}')
You can read more about strings and variable substitutions in Bash here.
This question already has answers here:
How do I use variables in single quoted strings?
(8 answers)
Closed 6 years ago.
I have a simple function in my bashrc file, it takes 2 arguments and makes a curl call. The problem is, the curl request is not getting the variable. Here's the function...
checkUserName() {
cd ~/
echo "checking for username $2"
curl -w "#curl-format.txt" -H "Content-Type: application/json" -X POST -d '{"userName": "$2"}' http://localhost:8080/$1/verify
}
alias unameCheck=checkUserName
Then I call it with something like...
unameCheck users danwguy
and I will see...
checking for username danwguy
in my terminal prompt, however when I look at my logs from my application it shows that it is checking for userName $2
So the variable isn't being replaced in the curl command, even though the $1 is being replaced, since it is calling the correct API on my localhost.
It replaces it in the echo command, but not in the curl command.
I have even tried creating a local variable, but that still doesn't work, no matter what I do, it doesn't replace in the curl call, but it does in the echo call.
Can anyone see why it wouldn't be properly replacing the $2
Parameter expansions ($var) will not expand in single quotes. Use double quotes instead:
$ curl -w "#curl-format.txt" \
-H "Content-Type: application/json" \
-X POST \
-d '{"userName": "'"$2"'"}' \
"http://localhost:8080/$1/verify"
Also wrap parameter expansions in double quotes to avoid word splitting and
pathname expansion.
Just a note to previous comment.
You can escape double quotes with backslash, to tell bash interpreter to not interpret its special meaning, so final code looks like:
... -d "{\"userName\": \"$2\"}" ...
Which is way more obvious for me...
This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 2 months ago.
I have this simple task and I've spent a few hours already trying to figure out how can I use a variable inside a curl call within my bash script:
message="Hello there"
curl -X POST -H 'Content-type: application/json' --data '{"text": "${message}"}'
This is outputting ${message}, literally because it's inside a single quote. If I change the quotes and put double outside and single inside, it says command not found: Hello and then command not found: there.
How can I make this work?
Variables are not expanded within single-quotes. Rewrite using double-quotes:
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"${message}\"}"
Just remember that double-quotes within double-quotes have to be escaped.
Another variation could be:
curl -X POST -H 'Content-type: application/json' --data '{"text": "'"${message}"'"}'
This one breaks out of the single quotes, encloses ${message} within double-quotes to prevent word splitting, and then finishes with another single-quoted string. That is:
... '{"text": "'"${message}"'"}'
^^^^^^^^^^^^
single-quoted string
... '{"text": "'"${message}"'"}'
^^^^^^^^^^^^
double-quoted string
... '{"text": "'"${message}"'"}'
^^^^
single-quoted string
However, as the other answer and #Charles Duffy pointed out in a comment, this is not a robust solution, because literal " and other characters in $message may break the JSON.
Use the other solution, which passes the content of $message to jq in a safe way, and jq takes care of correct escaping.
While the other post (and shellcheck) correctly points out that single quotes prevent variable expansion, the robust solution is to use a JSON tool like jq:
message="Hello there"
curl -X POST -H 'Content-type: application/json' \
--data "$(jq -n --arg var "$message" '.text = $var')"
This works correctly even when $message contains quotes and backslashes, while just injecting it in a JSON string can cause data corruption, invalid JSON or security issues.