无法解析 json 内的参数

无法解析 json 内的参数

我在脚本 ( edm.ksh) 中使用curl 命令从 API 检索一些数据,它需要 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 编码,这意味着您限制密码中允许的字符。
  • 几个 shell 变量要么是单引号的(意味着它们不会扩展为它们的值),要么是不带引号的(意味着 shell 将扩展它们的值并在空格上分割它并在扩展位上执行文件名通配)。

假设密码是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"

请注意,以这种方式读取密码仍会删除密码值中的尾随空格(这是由于命令替换所致)。

创建一个 JSON 文档,其中包含读取的密码字符串作为密钥的值,password可以使用以下命令完成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 对象中。该 shell 变量也不需要导出。

例子:

$ 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

我在此处提供的代码中的任何引用都不是偶然或多余的。必须对所有扩展使用双引号,以便 shell 不会拆分变量中的字符串或以特殊方式解释字符。参见例如什么时候需要双引号?


将以上所有内容收集在一个脚本中,不进行错误处理,删除json_payloadshell 变量(因为不需要),并使用快捷--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

相关内容