How to put a shell parameter in a string inside a string? - bash

There is a parameter $1. It's an email address. I want it to be part of the string within a string of this curl command:
curl 'xy.com' --data-binary '{"email":"variableValueHere!!!"}'
So a command including the parameter $1 should result in this command...
curl 'xy.com' --data-binary '{"email":"xy#z.de"}'
if $1 equals xy#z.de.
How can I put it in there?
What I tried so far:
curl 'xy.com' --data-binary '{"email":"$1"}'
curl 'xy.com' --data-binary '{"email":"`echo $1`"}'

Try this:
curl 'xy.com' --data-binary '{"email":"'"$1"'"}'
It's the concatenation of
'{"email":"'
"$1"
'"}'
and inserts your parameter as a quoted string.

Better use a proper JSON parser like jq:
curl 'xy.com' --data-binary "$(
jq \
--arg email "$1" \
--null-input \
--compact-output \
'.email = $email'
)"
"$(jq ...)": Captures the output of jq as a string.
jq: Is a command-line JSON processor.
--arg email "$1": Pass the shell's argument $1's value as the jq variable $email.
--null-input: Tells jq there is no JSON input stream to parse.
--compact-output: Tells jq to compact its output by putting each JSON object on a single line.
'.email = $email': This is the jq query to assign the value of the $email variable as the JSON string value of the email key from the root JSON object ..
This can also be written more compact:
curl 'xy.com' --data-binary "$(jq -cn --arg e "$1" '.email=$e')"

What do you see when you try this:
curl 'xy.com' --data-binary '{"email":"`$1`"}'

How about
curl xy.com --data-binary "{email:$1}"
?
If you want the 3rd argument to be in JSON Format, write it as:
curl xy.com --data-binary '{"email":"'"$1"'"}'
You can simplify this to
curl xy.com --data-binary '{"email":"'$1'"}'
if you are sure that your email address ($1) does not contain spaces or other troublesome characters.
If you really want to pass additional single quotes to curl (as you stated in your comment), just prepend and append to your argument a
"'"

Related

Mutiple varaibles in while loop of bash scripting

Suppose i have the below curl where i will be reading two of the varaibles from a file.how can we accomodate both the varaibles in a single while loop
while read p; do
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'HTTP_X_MERCHANT_CODE: STA' --header 'AK-Client-IP: 135.71.173.56' --header 'Authorization: Basic qwrewrereererweer' -d '{
"request_details": [
{
"id": "$p", #first dynamic varaible which will be fetched from the file file.txt
"id_id": "$q", #second dynamic varaible to be fetched from the file file.txt
"reason": "Pickup reattempts exhausted"
}
]
}' api.stack.com/ask
done<file.txt
file.tx will have two columns from which the dynamic variables whill be fetched to the above curl. Pls let me know how can we accomodate both the variable in the above while loop
i will need bit of a help regarding the same
Since you'll want to use a tool like jq to construct the payload anyway, you should let jq parse the file instead of using the shell.
filter='split(" ") |
{ request_details: [
{
id: .[0],
id_id: .[1],
reason: "Pickup reattempts exhausted"
}
]
}'
jq -cR "$filter" file.txt |
while IFS= read -r payload; do
curl -X POST --header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'HTTP_X_MERCHANT_CODE: STA' \
--header 'AK-Client-IP: 135.71.173.56' \
--header 'Authorization: Basic qwrewrereererweer' \
-d "$payload"
done
The -c option to jq ensures the entire output appears on one line: curl doesn't need a pretty-printed JSON value.
read accepts multiple target variable names. The last one receives all the content not yet read from the line. So read p reads the whole line, read p q would read the first token (separated by whitespace) into p and the rest into q, and read p q r would read the first two tokens into p and q and any remaining junk into r (for example if you want to support comments or extra tokens in file.txt).

Bash script to make curl POST request based on file txt line used in data raw

I'm getting the code below
#!/bin/bash
input="processes.txt"
while IFS= read -r line
do
curl --location --request POST 'https://api.controllegal.zymdev.com/v2/getProcessesInfo' \
--header 'Content-Type: application/json' \
--data-raw '{
"data":{
"process_id": "$line",
"location_id":"11001",
"entity":"608-True-3110-11001"
}
}'
done < "$input"
from Postman to make a cURL POST request and using it in a bash script to loop a txt file line and send it in the data json raw, but for some reason it returns
false
each time the curl get executed
when doing
echo $line
it prints fine the line string which is a something like "11001010200020160112400"
and if I use the string directly in the data-raw it works fine.
I tried using double quotes like
""$line""
but it throws
Unexpected token $ in JSON
In bash, a pair of single-quotes (') prevents variable substitution inside. You would need to do something like
--data-raw "{
\"data\":{
\"process_id\": \"$line\",
...
"
so that the value of $line gets substituted.

Awk or other command how to get variable value on string curl results?

in the bash script I'm running a curl for POST request getting data
f_curl_get_data (){
read -p "start date : " start_date
read -p "end date : " end_date
# (!) NOTE
# - the date time format must be YYYY-MM-DD
mng_type=users
user=myuser
secret=mysecret
curl --location --request POST 'https://myapi.com/api/v2.1/rest/exports' \
--header 'Content-Type: application/json' \
--header 'SDK-APP-ID: '$user'' \
--header 'SDK-SECRET: '$secret'' \
--data-raw '{
"type":"'$mng_type'",
"start_date":"'$start_date'",
"end_date": "'$end_date'"
}'
}
and I get the following results
{"results":{"created_at":"2020-03-13T07:04:14Z","download_url":"","error_message":"","original_filename":"2020-03-13T07:04:14Z_exported_users.json","percentage":0,"resource_name":"users","size":0,"status":"started","total_rows":0,"unique_id":"37c23e60-5b83-404a-bd1f-6733ef04463b"},"status":200}
how do I just get the value from the variable "unique_id" with awk command or other?
37c23e60-5b83-404a-bd1f-6733ef04463b
thank u
Using sed
sed -e 's/.*unique_id":"\(.*\)\"}.*/\1/'
Demo :
:>echo '{"results":{"created_at":"2020-03-13T07:04:14Z","download_url":"","error_message":"","original_filename":"2020-03-13T07:04:14Z_exported_users.json","percentage":0,"resource_name":"users","size":0,"status":"started","total_rows":0,"unique_id":"37c23e60-5b83-404a-bd1f-6733ef04463b"},"status":200}' | sed -e 's/.*unique_id":"\(.*\)\"}.*/\1/'
37c23e60-5b83-404a-bd1f-6733ef04463b
Using GNU awk and json extension:
$ gawk '
#load "json" # load extension
{
lines=lines $0 # in case of multiline json file
if(json_fromJSON(lines,data)!=0) { # explode valid json to an array
print data["results"]["unique_id"] # print the object value
lines="" # in case there is more json left
}
}' file
Output:
37c23e60-5b83-404a-bd1f-6733ef04463b
Extension can be found in there:
http://gawkextlib.sourceforge.net/json/json.html
... or you could use jq:
$ jq -r '.results.unique_id' file
37c23e60-5b83-404a-bd1f-6733ef04463b

How to write oneline string in multipe lines?

I want to send a big json with long string field by curl, how should I crop it to multiple lines? For example:
curl -X POST 'localhost:3000/upload' \
-H 'Content-Type: application/json'
-d "{
\"markdown\": \"# $TITLE\\n\\nsome content with multiple lines....\\n\\nsome content with multiple lines....\\n\\nsome content with multiple lines....\\n\\nsome content with multiple lines....\\n\\n\"
}"
Use a tool like jq to generate your JSON, rather than trying to manually construct it. Build the multiline string in the shell, and let jq encode it. Most importantly, this avoids any potential errors that could arise from TITLE containing characters that would need to be correctly escaped when forming your JSON value.
my_str="# $TITLE
some content with multiple lines...
some content with multiple lines...
some content with multiple lines..."
my_json=$(jq --argjson v "$my_str" '{markdown: $v}')
curl -X POST 'localhost:3000/upload' \
-H 'Content-Type: application/json' \
-d "$my_json"
curl has the ability to read the data for -d from standard input, which means you can pipe the output of jq directly to curl:
jq --argjson v "$my_str" '{markdown: $v}' | curl ... -d#-
You can split anything to multiple lines using the technique already in your post, by terminating lines with \.
If you need to split in the middle of a quoted string,
terminate the quote and start a new one.
For example these are equivalent:
echo "foobar"
echo "foo""bar"
echo "foo"\
"bar"
But for your specific example I recommend a much better way.
Creating the JSON in a double-quoted string is highly error prone,
because of having to escape all the internal double-quotes,
which becomes hard to read and maintain as well.
A better alternative is to use a here-document,
pipe it to curl, and use -d#- to make it read the JSON from stdin.
Like this:
formatJson() {
cat << EOF
{
"markdown": "some content with $variable in it"
}
EOF
}
formatJson | curl -X POST 'localhost:3000/upload' \
-H 'Content-Type: application/json'
-d#-
If I were you, I'd save the JSON to a file:
curl -X POST 'localhost:3000/upload' \
-H 'Content-Type: application/json' \
-d "$(cat my_json.json)"

How to send emoji via bash script to Telegram bot using curl?

I'm trying to send an emoji/emoticon to my Telegram bot using a bash script. This bash script calls the Telegram API as follows:
curl -s -X POST 'https://api.telegram.org/'$API'/sendMessage' -F chat_id=$chat -F text=$text
Since the bash script isn't unicode, I cannot simply copy/paste the emojis from the web. Therefore I tried using the UTF-8 emoji variants, but the backslash character keeps getting escaped.
The expected json output should be as follows: "text":"\ud83d\udd14"
Instead, this is what I get:
Input: $text = \xF0\x9F\x98\x81
JSON Output = "text":"\\xF0\\x9F\\x98\\x81\\"
Input: $text = u'\U0001F604'
JSON Output = "text": "u'\\U0001F604'\"
Input: $text = \U0001F514
JSON Output = "text":"\\U0001F514"
Input: $text = "(1f600)"
JSON Output = "text":"\"(1f600)\""
Input: $text = \ud83d\ude08
JSON Output = "text":"\\ud83d\\ude08"
Input: $text = \\\ud83d\\\udd14
JSON Output = "text":"\\\\\\ud83d\\\\\\udd14"
What is the correct syntax to send an emoji using a bash script and curl to my Telegram bot?
Thank you very much!
Generating JSON For The Telegram API
If your question is about JSON encoding, let jq figure it out for you:
s='🔔' ## or s=$'\360\237\224\224'
json=$(jq -anc --arg id "$chat" --arg s "$s" '{"chat_id": $id, "text": $s}')
curl -X POST -H "Content-Type: application/json" -d "$json" \
"https://api.telegram.org/$API/sendMessage"
From JSON To String Literal
In bash 4.0 or newer, the shell itself can be asked to give you an ASCII-printable literal string which will correspond to a multi-byte character.
LC_ALL=C printf "s=%q\n" "$(jq -r . <<<'"\ud83d\udd14"')"
...will output:
s=$'\360\237\224\224'
From String Literal To JSON
To go in the other direction:
s=$'\360\237\224\224'
jq -anM --arg s "$s" '$s'
...emits as output:
"\ud83d\udd14"
You can use echo -e '\U0001F514' for get emoji
curl -F "text=`echo -e '\U0001F514'` - it's a bell" "https://api.telegram.org/$API/sendMessage?chat_id=$chat"
or $'\U0001F514'
curl -F "text="$'\U0001F514'" - it's a bell" "https://api.telegram.org/$API/sendMessage?chat_id=$chat"

Resources