引用符付きの文字列の引用符をエスケープします。

引用符付きの文字列の引用符をエスケープします。

curlx-www-form-urlencodeを使用してファイル内でPOST JSONデータを実行しようとしていますdocker-compose。この例では、このパブリックウェブサイトを使用しており、次のように応答する必要があります。

# sh -c 'curl http://httpbin.org/post -F "json={\"key\": \"value\"}"'
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "json": "{\"key\": \"value\"}"
  }, ...

これは外部の一重引用符でうまく機能しますが、内部に変数があるため、二重引用符が必要です。したがって、このコマンドは機能せず、入れ子になった引用符をエスケープする正しい構文を見つけることはできません。

# sh -c "curl http://httpbin.org/post -F "json={\"key\": \"$VAR\"}""
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "json": "{key:"
  }, 

答え1

送信されるパラメータに挿入するデータcurlは、JSON文書をエンコードするJSONエンコード文字列です。

文字列は次のように別々に生成できます。

json_string=$( jq -n --arg 'my key' 'my "value"' '$ARGS.named|@json' )

JSON認識ツールを使用してjqデータをJSONエンコード文字列に変換することで、文字列の内容が有効なJSON文字列であり、指定されたキー、およびを含むmy key有効なJSON文書にデコードできることを確認します。値、my "value"

上記の正確なコマンドは文字列"{\"my key\":\"my \\\"value\\\"\"}"をに割り当てますjson_string

curlその後、次のようにパラメータからこの文字列を使用して直接呼び出すことができます。

curl 'http://httpbin.org/post' -F "json=$json_string"

sh -c...または、次のように文字列をそのスクリプトにパラメータとして渡して、インラインスクリプトから呼び出すことができます。

sh -c 'curl "http://httpbin.org/post" -F "json=$1"' sh "$json_string"

これらの呼び出しの1つは、curl次の応答を取得します。

{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "json": "{\"my key\":\"my \\\"value\\\"\"}"
  },
  "headers": {
    "Accept": "*/*",
    "Content-Length": "160",
    "Content-Type": "multipart/form-data; boundary=------------------------f805cf070f665e7e",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.84.0",
    "X-Amzn-Trace-Id": "Root=1-83012651-2995681c270059da2906c40f"
  },
  "json": null,
  "origin": "xxx.xxx.xxx.xxx",
  "url": "http://httpbin.org/post"
}

JSONドキュメントをJSON文字列にエンコードすることはそれcurl自体で行われるように見えるので、必ずしも必要ではありません。

json_string=$( jq -n -c --arg 'my key' 'my "value"' '$ARGS.named' )

jo...JSON文字列を生成するか、インストールした場合は短い文字列を生成します。

json_string=$( jo 'my key'='my "value"' )

答え2

このように?

$ var=hello
$ sh -c "curl http://httpbin.org/post -F 'json={\"key\": \"$var\"}'"
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "json": "{\"key\": \"hello\"}"
  }, 

メモ:

$ sh -c "curl http://httpbin.org/post -F 'json={\"key\": \"$var\"}'"
        1                                2       3    3   34    3 21

(1)外側二重引用符、(2)一重引用符、いいえ内部二重引用符は特別なので、エスケープする必要はありません。 (3)内部二重引用符は外部二重引用符に対してエスケープされます。 (4)実行する前に、外部二重引用符内に変数拡張を実行しますsh -c(変数の値に一重引用符がある場合は、内部シェルに問題が発生し、そこに二重引用符がJSON構文を混乱させる可能性があることに注意してください)。

shBashで、を使用して実行すると、次の-xように実行されることがわかります。

+ curl http://httpbin.org/post -F 'json={"key": "hello"}'
                                  2      3   3  3     3 2 

これは見えるものとほぼ同じですsh -c。ここで、(2)は引用符付き文字列、(3)は文字列内の特殊でない二重引用符です。

(Dashの出力が明示的ではないため、「Bashで」と言いますset -x。Bashでは通常、引用された-x出力を再実行します。たとえば、コマンドを発行すると表示されますが、echo "foo bar"これecho 'foo bar'は実際には特別なケースを変更しません。) 。

答え3

Heredocsを使用すると、この引用をより簡単に管理できます。

sh <<END_SCRIPT
curl http://httpbin.org/post -F 'json={"key": "$VAR"}'
END_SCRIPT

Heredoc自体は参照されないため、変数が置き換えられます。

もしVAR="foo bar"、私達は得る

...
  "form": {
    "json": "{\"key\": \"foo bar\"}"
  },
...

心配する必要があるのは、変数の値に引用符が含まれているかどうかです。

VAR='She said "Hello"'無効なJSONが表示されます。

...
  "form": {
    "json": "{\"key\": \"She said \"Hello\"\"}"
  },
...

シェルパラメータ拡張を使用して、内部引用符をエスケープできます。

sh <<END_SCRIPT
curl http://httpbin.org/post -F 'json={"key": "${VAR//\"/\\\"}"}'
END_SCRIPT

〜する

...
  "form": {
    "json": "{\"key\": \"She said \\\"Hello\\\"\"}"
  },
...

関連情報