2014-01-29 54 views
12

我想发送一个json请求并在post数据中嵌入一个变量。 我做了一点研究,并提出了围绕变量的单引号。Bash脚本:在curl中使用字符串变量JSON Post data

#!/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 

不幸的是我得到了一些错误:

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存在一些问题与撑杆和HTTP应答状态,即不能被执行的命令。我的代码在这里有什么问题? 谢谢!

这是我的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 
+0

这似乎是一个高概率候选人'卷曲:(6)无法解析主机“ - D''。做一个“人卷曲”并搜索“--data”。祝你好运。 – shellter

+1

“d”选项之前的字符似乎是一些特殊的印刷破折号? – halfbit

+0

@halfbit:赶上! (好名字!) – shellter

回答

5

我的建议:

#!/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 

的差别是在-d连字符(而不是一个破折号)和周围$FILENAME双引号。

18

更新:使用简单

request_body=$(cat <<EOF 
{ 
    "jsonrpc": "2.0", 
    "method": "Player.Open", 
    "params": { 
    "item": { 
     "file": "$FILENAME" 
    } 
    } 
} 
EOF 
) 

而不是我在下面解释。但是,如果它是一个选项,请使用jq来生成JSON。这确保了$FILENAME的值被正确引用。

request_body=$(jq -n --arg fname "$FILENAME" ' 
{ 
    jsonrpc: "2.0", 
    method: "Player.Open", 
    params: {item: {file: $fname}} 
}' 

这将是简单的定义与请求主体的内容第一个变量:

#!/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 

这个定义可能需要一个解释明白,但要注意两大好处:

  1. 您消除了报价水平
  2. 为了便于阅读,您可以轻松地格式化文本。

首先,你有一个简单的命令替换,从文件中读取:

$(< ...) # bash improvement over $(cat ...) 

而不是文件名,但是,您指定的进程替换,其中使用了命令的输出就好像它是文件的主体一样。

过程替换中的命令只是 cat,它从here文档中读取。这是包含您的请求正文的文档。

+0

卡住了一个聪明的把戏。谢谢。这是完美的解决方案。 –

+0

只是好奇,'request_body = $(cat << EOF ... EOF)'有什么问题? – smac89

+1

@ smac89我真的不能告诉你为什么我写'$(<<(...))'而不是'$(...)'。在写这篇文章时,我可能会在脑海中琢磨几个不同的想法,这往往会导致一个奇怪而复杂的混合体,我无法简化。 – chepner

1

这里是将数据从文件插入JSON属性的另一种方法。 该解决方案基于名为jq的非常酷的命令。

下面是一个准备请求JSON数据,用来在数字海洋创建CoreOS液滴的例子:

# 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\"}") 
相关问题