我在脚本 ( 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 编码字符串,并将该字符串作为键值插入password
JSON 对象中。该 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_payload
shell 变量(因为不需要),并使用快捷--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