bashスクリプト関数で定義された変数でcurl POSTを使用する


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"

私は引用符に問題があると思いますが、私はそれらを何度も使っており、同様のエラーが発生しています。すべての変数は、実際のスクリプトのさまざまな関数で定義されています

回答:


274

カスタムヘッダーを囲む引用符をcurlに渡す必要はありません。また、data引数の中央にある変数は引用符で囲む必要があります。

まず、スクリプトの投稿データを生成する関数を記述します。これにより、シェルの引用に関するあらゆる種類の頭痛の種からあなたを救い、あなたの試みのようにcurlの呼び出し行に投稿データを供給するよりも、スクリプトの保守を読みやすくなります。

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"

これは、シェルのクォートルールに関するいくつかの説明です。

-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' "}} '
ツイストストリーム

3
2番目のEOFの後にスペースがあると機能しませんでしたEOF 。それを削除した後、すべてが正常です。
Klaas

2
@dbreauxこれは、curlコマンドを実行する場所によって異なります。コマンドがスクリプト内にある場合は、同じスクリプト内のその上のどこかに関数を定義するだけです。コマンドラインから直接curlを実行している場合、いくつかのオプションがあります。その1つは、新しいファイルに関数を入力してから、コマンドラインで実行source my_new_fileして、現在の環境で関数を定義することです。その後、示されているようにcurlコマンドを実行できます。
アトス卿

2
@slashdottirこれは、ヒアドキュメントと呼ばれるbash機能です。詳細については、このリンクを参照してください。特に、例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.スペースを含む入力の場合:ie
を追加して変数をラップします。""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 2017

1
承知しました。i="a b"forループの代わり
Vasyl Boroviak 2017

5
承認され、2番目に投票された回答がで機能しないことがわかりました/bin/sh。しかし、この答えはうまくいきました。そして、それは他の答えよりもはるかに簡単です。どうもありがとうございます!私はいくつかのより良い行折り返しフォーマットであなたの答えを編集しました。そうでなければ、輝きを見つけるのは難しいです。乾杯の仲間
Vasyl Boroviak 2017

1
あなたは私の多くの時間を保存し、多く@pbaranskiおかげで
のSudhir tataraju

32

Curlはファイルからバイナリデータをポストできるため、curlで厄介なものをポストし、現在のシェルの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  }

ご覧のとおり、ヒアドキュメントでサブシェルとwhatnotだけでなく参照変数を呼び出すことができます。幸せなハッキングがこれがに役立つことを願っています'"'"'""""'''""''


2
Zabbixからのアラートでそれを呼び出そうとしていたので、他の答えはうまくいきませんでした。これは完全に解決し、よりクリーンになります。
0rkan 2016年

しかし、コードをbash関数に配置するとどうなるでしょうか。myFunction(){....}?
Hanynowsky

1
このレシピは、スクリプトが逐語的にコピーされた場合にのみ機能することに注意してください(つまり、EOF、中括弧などの再フォーマットを行わない)
Vader B

9

数年遅れますが、evalまたはbacktick置換を使用している場合、これは誰かを助けるかもしれません:

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
  • アトス卿からの情報は完璧に機能しました!!

これが、couchDBのcurlスクリプトで使用する方法です。それは本当に大いに役立った。ありがとう!

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がファイルからデータを投稿できることを指摘し、過度の引用エスケープを回避し、JSONを新しい行に明確に分割するためにヒアドキュメントを採用しています。ただし、curlは標準入力からデータをポストできるため、関数を定義したり、catから出力をキャプチャしたりする必要はありません。このフォームはとても読みやすいです:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.