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エンコード文字列としてエンコードされ、password
JSONオブジェクトにキー値として挿入されます。このシェル変数もエクスポートする必要はありません。
例:
$ 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\""}
curl
API エンドポイントを呼び出すには、以下を使用します。
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