jsonはパラメータを解析できません。

jsonはパラメータを解析できません。

APIから一部のデータを取得するには、スクリプト(edm.ksh)でcurlコマンドを使用していますが、JSON形式のパスワードが必要です{"password":"myPassword"}。たとえば、myPasswordハードコーディングされておらず、edm.ksh私が抽出した設定ファイルからインポートされます。変わりやすい。

edm.ksh:

#! /usr/bin/ksh
export PASSWORD=$(grep PASSWORD /home/dummy/password.txt | awk -F " " '{print $2}')
export PASSWORD_TXT=$(echo -e "'"'{"password":"'${PASSWORD}'"}'"'")
curl -k -X POST -d $PASSWORD_TXT ${LDAP_URL} > ${TEMP_DIR}/token.dat
$ cat /home/dummy/password.txt
PASSWORD myPassword

スクリプトを実行すると、$ PASSWORD_TXTが解析されることを期待してスクリプトに出力され'{"password":"myPassword"}'ます。$'\'{"password":"myPassword"}\''コマンドラインでは完全に解析しますが、スクリプトでは解析しません。エスケープ文字を使用して正しいjson解析を実行する方法について役立つ人はいますか?

私も次のことを試しました

curl -k -X POST -d  '{"password":"${PASSWORD_TXT}"}' ${LDAP_URL} > ${TEMP_DIR}/token.dat

ただし、変数はJSONで解析されません。

この問題の手がかりが得られたら、とても感謝します。

よろしくお願いします!

答え1

表示したコードにはいくつかの問題があります。

  • ファイルからパスワードを読み取る方法では、パスワードにスペースやその他のスペースが含まれていないと仮定します。
  • パスワードを含むJSON文書は、パスワード文字列をJSONにエンコードしません。これは、パスワードに許可される文字を制限することを意味します。
  • 複数のシェル変数は、単一引用符(対応する値に拡張されないことを意味)または引用符がありません(シェルがその値を拡張し、スペースに分割し、拡張ビット名ワイルドカードでファイルを実行することを意味します)。

パスワードがPASSWORD文字列で始まる行の最初のスペースの後のファイル行の残りの部分であると仮定すると、password.txt次のようにパスワードを読み取ることができます。

password=$( sed -e '/^PASSWORD /!d' -e 's///' -e q <password.txt )

これにより、で始まらないすべての行が削除されPASSWORD、それを含む最初の行からプレフィックス文字列が削除され、結果が印刷され、ファイルの処理が停止します。このpassword変数はエクスポートする必要はありません。

例:

$ cat password.txt
PASSWORD this is "the password"
$ password=$( sed -e '/^PASSWORD /!d' -e 's///' -e q <password.txt )
$ printf 'Password: %s\n' "$password"
Password: this is "the password"

この方法でパスワードを読み取ると、パスワード値の末尾のスペースが削除されます(これはコマンドの置き換えによるものです)。

password次のコマンドを使用して、読み取りパスワード文字列をキー値として含むJSONドキュメントを生成できます.JSON処理ツールjq:

json_payload=$( jq -n -c --arg password "$password" '$ARGS.named' )

または以下を使用してください。コマンドラインJSONビルダーjo

json_payload=$( jo password="$password" )

または以下を使用してください。Millerは、一般的な構造化された文書形式を操作するために選択されたツールです。

json_payload=$( mlr -n --ojsonl put -s password="$password" 'end { emit @password }' )

またはPythonを使用して

json_payload=$( python -c 'import sys, json; print(json.dumps({"password": sys.argv[1]}))' "$password" )

またはPerlを使用して

json_payload=$( perl -MJSON -e 'print encode_json({"password" => $ARGV[0]});' "$password" )

パスワードに含まれる文字に関係なく、文字列は有効なJSONエンコード文字列としてエンコードされ、passwordJSONオブジェクトにキー値として挿入されます。このシェル変数もエクスポートする必要はありません。

例:

$ printf 'Password: %s\n' "$password"
Password: this is "the password"
$ json_payload=$( jq -n -c --arg password "$password" '$ARGS.named' )
$ printf 'JSON document: %s\n' "$json_payload"
JSON document: {"password":"this is \"the password\""}

curlAPI エンドポイントを呼び出すには、以下を使用します。

curl --silent \
    --request POST \
    --header 'Content-Type: application/json' \
    --data "$json_payload" "$api_endpoint_url" >output

ここに提供するコードのすべての参照は偶然でも重複もありません。シェルが変数の文字列を分割したり、文字を特別な方法で解釈したりしないように、すべての拡張に二重引用符を使用する必要があります。たとえば、参照してください。いつ二重引用符が必要ですか?


上記のすべての項目をスクリプトに収集し、エラー処理を実行せず、json_payloadシェル変数を削除し(必要でない場合)使用します。ショートカット--jsonオプションそしてcurl

#!/bin/sh

api_endpoint_url='some URL here'

password=$( sed -e '/^PASSWORD /!d' -e 's///' -e q <password.txt )

jq -n -c --arg password "$password" '$ARGS.named' |
curl --silent --json @- "$api_endpoint_url" >output

関連情報