Bash 脚本:在 curl JSON Post 数据中使用字符串变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21440569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script: Use string variable in curl JSON Post data
提问by tzippy
I want to send a json request and embedd a variable in the post data. I did a little research and I came up with the single quotes around the variable.
我想发送一个 json 请求并在帖子数据中嵌入一个变量。我做了一些研究,我想出了围绕变量的单引号。
#!/bin/bash
FILENAME="/media/file.avi"
curl -i -X POST -H "Content-Type: application/json" —d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'$FILENAME'"}}}' http://192.167.0.13/jsonrpc
Unfortunately I get some errors:
不幸的是,我收到了一些错误:
curl: (6) Couldn't resolve host '—d'
curl: (3) [globbing] nested braces not supported at pos 54
HTTP/1.1 200 OK
Content-Length: 76
Content-Type: application/json
Date: Wed, 29 Jan 2014 19:16:56 GMT
{"error":{"code":-32700,"message":"Parse error."},"id":null,"jsonrpc":"2.0"}
Appearently there are some problems with the braces and the http answer states, that the command could not be executed. What's wrong with my code here? Thanks!
显然大括号和 http 回答状态存在一些问题,即无法执行命令。我这里的代码有什么问题?谢谢!
This is my curlversion:
这是我的curl版本:
curl 7.30.0 (mips-unknown-linux-gnu) libcurl/7.30.0 OpenSSL/0.9.8y
Protocols: file ftp ftps http https imap imaps pop3 pop3s rtsp smtp smtps tftp
Features: IPv6 Largefile NTLM NTLM_WB SSL
回答by chepner
Update: use the simpler
更新:使用更简单的
request_body=$(cat <<EOF
{
"jsonrpc": "2.0",
"method": "Player.Open",
"params": {
"item": {
"file": "$FILENAME"
}
}
}
EOF
)
rather than what I explain below. However, if it is an option, use jqto generate the JSON instead. This ensures that the value of $FILENAMEis properly quoted.
而不是我在下面解释的。但是,如果它是一个选项,请jq改为使用生成 JSON。这可确保$FILENAME正确引用的值。
request_body=$(jq -n --arg fname "$FILENAME" '
{
jsonrpc: "2.0",
method: "Player.Open",
params: {item: {file: $fname}}
}'
It would be simpler to define a variable with the contents of the request body first:
首先用请求正文的内容定义一个变量会更简单:
#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
"jsonrpc": "2.0",
"method": "Player.Open",
"params": {
"item": {
"file": "$FILENAME"
}
}
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc
This definition might require an explanation to understand, but note two big benefits:
- You eliminate a level of quoting
- You can easily format the text for readability.
First, you have a simple command substitution that reads from a file:
$( < ... ) # bash improvement over $( cat ... )
Instead of a file name, though, you specify a process substitution, in which the output of a command is used as if it were the body of a file.
#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
"jsonrpc": "2.0",
"method": "Player.Open",
"params": {
"item": {
"file": "$FILENAME"
}
}
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc
这个定义可能需要解释才能理解,但请注意两大好处:
- 你消除了一个引用级别
- 您可以轻松地格式化文本以提高可读性。
首先,您有一个从文件中读取的简单命令替换:
$( < ... ) # bash improvement over $( cat ... )
但是,您指定了一个进程替换,而不是文件名,在其中使用命令的输出,就好像它是文件的主体一样。
The command in the process substitution is simply cat, which reads from a here document. It is the here document that contains your request body.
进程替换中的命令很简单cat,它从这里的文档中读取。这是包含您的请求正文的此处文档。
回答by Hln
My suggestion:
我的建议:
#!/bin/bash
FILENAME="/media/file 2.avi"
curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'"$FILENAME"'"}}}' http://192.167.0.13/jsonrpc
The differences are hyphen in -d(instead of a dash) and double quotes around $FILENAME.
区别在于连字符-d(而不是破折号)和周围的双引号$FILENAME。
回答by czerasz
Here is another way to insert data from a file into a JSON property.
This solution is based on a really cool command called jq.
这是将文件中的数据插入 JSON 属性的另一种方法。此解决方案基于一个非常酷的命令,称为jq.
Below is an example which prepares request JSON data, used to create a CoreOS droplet on Digital Ocean:
下面是一个准备请求 JSON 数据的示例,用于在 Digital Ocean 上创建 CoreOS Droplet:
# Load the cloud config to variable
user_data=$(cat config/cloud-config)
# Prepare the request data
request_data='{
"name": "server name",
"region": "fra1",
"size": "512mb",
"image": "coreos-stable",
"backups": false,
"ipv6": true,
"user_data": "---this content will be replaced---",
"ssh_keys": [1234, 2345]
}'
# Insert data from file into the user_data property
request_data=$(echo $request_data | jq ". + {user_data: \"$user_data\"}")

