将curl POST与bash脚本函数中定义的变量一起使用


176

当我回声时,我得到了它,当我将其输入到终端时,它将运行

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"akdgdtk@test.com","screenName":"akdgdtk","type":"NIKE","passwordSettings":{"password":"Starwars1","passwordConfirm":"Starwars1"}},"firstName":"Test","lastName":"User","middleName":"ObiWan","locale":"en_US","registrationSiteId":"520","receiveEmail":"false","dateOfBirth":"1984-12-25","mobileNumber":"9175555555","gender":"male","fuelActivationDate":"2010-10-22","postalCode":"10022","country":"US","city":"Beverton","state":"OR","bio":"This is a test user","jpFirstNameKana":"unsure","jpLastNameKana":"ofthis","height":"80","weight":"175","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}' https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx

但是在bash脚本文件中运行时,出现此错误

curl: (6) Could not resolve host: application; nodename nor servname provided, or not known
curl: (6) Could not resolve host: is; nodename nor servname provided, or not known
curl: (6) Could not resolve host: a; nodename nor servname provided, or not known
curl: (6) Could not resolve host: test; nodename nor servname provided, or not known
curl: (3) [globbing] unmatched close brace/bracket at pos 158

这是文件中的代码

curl -i \
-H '"'Accept: application/json'"' \
-H '"'Content-Type:application/json'"' \
-X POST --data "'"'{"account":{"email":"'$email'","screenName":"'$screenName'","type":"'$theType'","passwordSettings":{"password":"'$password'","passwordConfirm":"'$password'"}},"firstName":"'$firstName'","lastName":"'$lastName'","middleName":"'$middleName'","locale":"'$locale'","registrationSiteId":"'$registrationSiteId'","receiveEmail":"'$receiveEmail'","dateOfBirth":"'$dob'","mobileNumber":"'$mobileNumber'","gender":"'$gender'","fuelActivationDate":"'$fuelActivationDate'","postalCode":"'$postalCode'","country":"'$country'","city":"'$city'","state":"'$state'","bio":"'$bio'","jpFirstNameKana":"'$jpFirstNameKana'","jpLastNameKana":"'$jpLastNameKana'","height":"'$height'","weight":"'$weight'","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}'"'" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

我认为引号存在问题,但是我经常使用它们,而且也遇到了类似的错误。在实际脚本中,所有变量都使用不同的功能定义

Answers:


274

您无需传递引号将自定义标头括起来即可卷曲。另外,data应在参数中间加上变量。

首先,编写一个函数来生成脚本的发布数据。这使您免于有关shell引用的种种麻烦,并且使读取维护脚本比在curl的调用行上输入post数据更容易,如您的尝试:

generate_post_data()
{
  cat <<EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
}

然后很容易在curl的调用中使用该函数:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

就是说,这里有一些关于shell引用规则的说明:

-H参数中的双引号(如所示-H "foo bar")告诉bash将内部内容作为单个参数保留(即使它包含空格)。

--data参数中的单引号(如中的--data 'foo bar')执行相同的操作,只是它们逐字传递所有文本(包括双引号字符和美元符号)。

要在单引号引起的文本中间插入变量,您必须结束单引号,然后将其与双引号变量连接,然后重新打开单引号以继续文本:'foo bar'"$variable"'more foo'


9
“'” $ <变量名称>“'”解决了我需要避免省略引号的问题。谢谢。
乌斯曼2015年

1
此解决方案有效,但我认为您可以在变量周围发出额外的双引号。因此,您可以执行以下操作:--data'{“ account”:{“ email”:“'”“ $ email”'“}}',而不是:--data'{” account“:{” email“:” '$ email'“}}'
twistedstream

3
当第二个EOF之后有空格时,该按钮不起作用EOF 。删除后,一切都很好。
克拉斯

2
@dbreaux这取决于您在哪里运行curl命令。如果命令在脚本中,则只需在同一脚本中它上方的任何位置定义函数。如果直接从命令行运行curl,则有几种选择,其中一种是在新文件中键入该函数,然后在命令行运行source my_new_file以在当前环境中定义该函数。之后,您可以按照指示运行curl命令。
阿索斯爵士

2
@slashdottir这是一个bash功能,称为Here Documents。您可以在此链接上详细了解它-特别是查看示例19-5。关于SO 这里已经有一个完整的问题
阿索斯爵士

103

使用https://httpbin.org/和内联bash脚本测试的解决方案
1.对于其中没有空格的变量,即1:在替换所需字符串之前和之后
简单添加'$variable

for i in {1..3}; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"number":"'$i'"}' "https://httpbin.org/post"; \
done

2.对于带空格的输入:
用其他空格包装变量,""el a"

declare -a arr=("el a" "el b" "el c"); for i in "${arr[@]}"; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"elem":"'"$i"'"}' "https://httpbin.org/post"; \
done

哇作品:)


1
$i包含空格时不起作用。:(
Vasyl Boroviak

你能举个例子吗?
pbaranski

1
当然。i="a b"而不是for循环
Vasyl Boroviak

5
我发现已接受的投票和第二投票的答案在中无效/bin/sh。但是,此答案确实有效。而且它比其他答案要简单得多。非常感谢!我已经使用一些更好的换行格式来编辑您的答案。否则,很难发现光彩。干杯伴侣
Vasyl Boroviak '17

1
非常感谢@pbaranski,您节省了我很多时间
sudhir tataraju 19-10-17

32

Curl可以发布文件中的二进制数据,因此,每当我需要发布带有curl的讨厌内容并且仍然想要访问当前shell中的var时,我就一直在使用进程替换并利用文件描述符。就像是:

curl "http://localhost:8080" \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
--data @<(cat <<EOF
{
  "me": "$USER",
  "something": $(date +%s)
  }
EOF
)

这看起来像是--data @/dev/fd/<some number>像普通文件一样被处理了。无论如何,如果您想看到它在本地运行,nc -l 8080请先运行,然后在不同的外壳中执行上述命令。您将看到类似以下内容:

POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: application/json
Content-Type:application/json
Content-Length: 43

{  "me": "username",  "something": 1465057519  }

如您所见,您可以在heredoc中调用子shell和诸如此类的子对象以及引用var。开心的骇客希望这可以帮助你'"'"'""""'''""''


2
另一个答案对我不起作用,因为我正试图在Zabbix的警报中调用它。这一个完美地解决了它,并且更加干净。
0rkan

但是,如果将代码放入bash函数中,该怎么办:myFunction(){....}?
Hanynowsky '16

1
值得一提的是,仅当脚本逐字复制时(即没有重新格式化EOF,花括号等),此配方才有效
Vader B

9

迟了几年,但是如果您使用eval或反引号替换,这可能会对某人有所帮助:

postDataJson="{\"guid\":\"$guid\",\"auth_token\":\"$token\"}"

使用sed从响应的开头和结尾去除引号

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')

4
  • 阿索斯爵士的信息非常有效!

这是我必须在我的curl脚本中将它用于长沙发DB的方式。它确实帮了很多忙。谢谢!

bin/curl -X PUT "db_domain_name_:5984/_config/vhosts/$1.couchdb" -d '"/'"$1"'/"' --user "admin:*****"

4

经过这里答案的指导后,这实际上对我有用:

export BASH_VARIABLE="[1,2,3]"
curl http://localhost:8080/path -d "$(cat <<EOF
{
  "name": $BASH_VARIABLE,
  "something": [
    "value1",
    "value2",
    "value3"
  ]
}
EOF
)" -H 'Content-Type: application/json'

2

现有的答案指出curl可以发布文件中的数据,并使用heredocs避免过多的引号转义,并将JSON明确地换行。但是,无需定义函数或捕获cat的输出,因为curl可以发布来自标准输入的数据。我发现此表格可读性强:

curl -X POST -H 'Content-Type:application/json' --data '$@-' ${API_URL} << EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.