【问题标题】:Using curl POST with variables defined in bash script functions将 curl POST 与 bash 脚本函数中定义的变量一起使用
【发布时间】:2013-06-06 11:08:28
【问题描述】:

当我回显时,我得到了这个,当我将它输入终端时运行

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"

我认为我的引号有问题,但我经常使用它们,并且遇到过类似的错误。所有变量都在实际脚本中用不同的函数定义

【问题讨论】:

    标签: json bash curl javascript-objects


    【解决方案1】:

    您不需要将包含自定义标题的引号传递给 curl。此外,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'

    【讨论】:

    • "'"$"'" 解决了我需要不省略引号的问题。谢谢。
    • 此解决方案有效,但我认为您可以在变量周围发出额外的双引号。所以代替这个: --data '{"account": {"email": "'"$email"'"} }' 你可以这样做: --data '{"account": {"email": " '$email'"} }'
    • 第二个 EOF 后有空格时不起作用:EOF 。删除后一切正常。
    • @dbreaux 这取决于你在哪里运行 curl 命令。如果命令在脚本中,您只需在同一脚本中的任何位置定义函数即可。如果您直接从命令行运行 curl,您有几个选项,其中之一是在新文件中键入函数,然后在命令行运行 source my_new_file 以在当前环境中定义函数。之后,您可以按照指示运行 curl 命令。
    • @slashdottir 这是一个名为 Here Documents 的 bash 功能。您可以在this link 上阅读有关它的更多详细信息 - 特别是请查看示例 19-5。 SO上也已经有full question about it
    【解决方案2】:
    • Athos 爵士提供的信息完美运行!!

    以下是我必须在我的 curl 脚本中为 couchDB 使用它的方法。它真的有帮助 出了很多。谢谢!

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

    【讨论】:

      【解决方案3】:

      Curl 可以从文件中发布二进制数据,因此我一直在使用进程替换并利用文件描述符,只要我需要使用 curl 发布令人讨厌的内容并且仍然想要访问当前 shell 中的变量。比如:

      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/&lt;some number&gt;,它只是像普通文件一样被处理。无论如何,如果你想看到它在本地工作,只需先运行nc -l 8080,然后在不同的 shell 中触发上述命令。你会看到类似的东西:

      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 中调用 subshel​​l 和诸如此类的东西以及引用 var。快乐的黑客希望这有助于'"'"'""""'''""''

      【讨论】:

      • 另一个答案对我不起作用,因为我试图在 Zabbix 的警报中调用它。这个完美解决了,更干净。
      • 但是如果你把代码放在一个 bash 函数中会怎样:myFunction () { .... } ?
      • 值得注意的是,这个配方只有在脚本被逐字复制时才有效(即没有重新格式化 EOF、大括号等)
      • 就简单性、可读性而言,我想说的最优雅的答案..
      【解决方案4】:

      使用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
      

      哇好用:)

      【讨论】:

      • $i 包含空格时不起作用。 :(
      • 你能举个例子吗?
      • 当然。 i="a b" 而不是 for 循环
      • 我发现接受和第二个投票的答案在/bin/sh 中不起作用。然而,这个答案成功了。它比其他答案简单得多。太感谢了!我已经用一些更好的换行格式编辑了你的答案。否则,很难发现光彩。干杯队友
      • 非常感谢@pbaranski 你节省了我很多时间
      【解决方案5】:

      晚了几年,但如果您使用 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/"$//')
      

      【讨论】:

        【解决方案6】:

        现有答案指出 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
        

        【讨论】:

          【解决方案7】:

          在此处的答案指导后,这对我真正有用:

          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'
          

          【讨论】:

            【解决方案8】:

            将数据放入 txt 文件对我有用

            bash --version
            GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
            curl --version
            curl 7.29.0 (x86_64-redhat-linux-gnu)
             cat curl_data.txt 
             {  "type":"index-pattern", "excludeExportDetails": true  }
            
            curl -X POST http://localhost:30560/api/saved_objects/_export -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$(cat curl_data.txt)" -o out.json
            

            【讨论】:

            • 当然可以,但是之后您需要清理一个讨厌的临时文件。这仅在 Windows 上才真正有用,在这种情况下您无法可靠地将变量插入字符串。
            【解决方案9】:

            我们可以使用单引号 ' 为 curl 分配一个 变量,并将 一些其他变量 包裹在双单双引号 "'" 中以在 中进行替换>卷曲变量。然后我们可以轻松地使用 curl-variable,这里是 MERGE

            例子:

            # other variables ... 
            REF_NAME="new-branch";
            
            # variable for curl using single quote => ' not double "
            MERGE='{
                "repository": "tmp",
                "command": "git",
                "args": [
                    "pull",
                    "origin",
                    "'"$REF_NAME"'"
                ],
                "options": {
                    "cwd": "/home/git/tmp"
                }
            }';
            

            注意这一行:

                "'"$REF_NAME"'"
            

            所以我们可以使用这个 bash 变量 $MERGE 并像往常一样调用 curl

            curl -s -X POST localhost:1365/M -H 'Content-Type: application/json' --data "$MERGE" 
            

            【讨论】:

            • 由于某种原因,shell 脚本转义了引号,占位符的正确引号组合为我做到了。 some_body='{"query":"/v1/'$some_id'","body":""}' curl --data "$some_body" 'https://some.url'
            猜你喜欢
            • 2014-02-21
            • 1970-01-01
            • 1970-01-01
            • 2019-12-20
            • 1970-01-01
            • 2015-10-01
            • 1970-01-01
            • 2015-08-17
            • 2010-12-08
            相关资源
            最近更新 更多