我有一个可用的 API (linode) 来更新域。因此,下面是一个正常的 API 调用,可以很好地更新数据:
#!/bin/bash
# hardcoded data for testing
LINODE_API_KEY=1234
domain_id=1931316
domain_name="abx.com"
domain_type="master"
domain_email="hello@abx.com"
domain_ttl=30
# Update the domain
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${LINODE_API_KEY}" \
-X PUT -d "{
\"domain\": \"${domain_name}\", \"type\": \"${domain_type}\", \"soa_email\": \"${domain_email}\", \"ttl_sec\": ${domain_ttl}
}" "https://api.linode.com/v4/domains/${domain_id}"
当我执行上面的更新 API 时,它工作正常,我得到的 json 响应如下:
{"id": 1931316, "type": "master", "domain": "abx.com", "tags": [], "group": "", "status": "active", "errors": "", "description": "", "soa_email": "hello@abx.com", "retry_sec": 0, "master_ips": [], "axfr_ips": [], "expire_sec": 0, "refresh_sec": 0, "ttl_sec": 30, "created": "2022-12-13T09:01:01", "updated": "2022-12-14T03:26:27"}
但问题是我想在数据中使用变量。所以我将上面的工作代码更改为这个(带有我想传递的额外数据):
#!/bin/bash
# hardcoded data for testing
LINODE_API_KEY=1234
domain_id=1931316
domain_name="abx.com"
domain_type="master"
domain_email="hello@abx.com"
domain_ttl=30
# This value must be provided first
if [ -z "${domain_name}" ]; then
echo "You must provide domain name"
exit 1
else
change_domain_name="\\\"domain\\\": \\\"${domain_name}\\\""
fi
if [ -n "${domain_type}" ]; then
change_domain_type=", \\\"type\\\": \\\"${domain_type}\\\""
else
change_domain_type=""
fi
if [ -n "${soa_email}" ]; then
change_domain_email=", \\\"soa_email\\\": \\\"${domain_email}\\\""
else
change_domain_email=""
fi
if [ -n "${domain_ttl}" ]; then
change_domain_ttl=", \\\"ttl_sec\\\": ${domain_ttl}"
else
change_domain_ttl=""
fi
update_string="${change_domain_name}${change_domain_type}${change_domain_email}${change_domain_ttl}"
# Update the domain
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${LINODE_API_KEY}" \
-X PUT -d "{
${update_string} # THE PROBLEM IS HERE WHEN USING THIS VARIABLE
}" "https://api.linode.com/v4/domains/${domain_id}"
API 会提示 Invalid JSON
{"errors": [{"reason": "Invalid JSON"}]}
但是当我使用 echo ${update_string}
变量时,我会得到与我使用的相同的数据语法,那么为什么它会提示这是无效的?
我什至可以将上面的回显结果复制粘贴回 -d 数据中,并且工作正常。
我将我的问题回滚到原来的问题,以解释为什么我使用上述方法而不是按照@Arnaud Valmary 的建议创建 jq --arg
。
例如,在这里我只想传递值 domain_name 和 domain_ttl。所以更新字符串的值将是这样的:
update_string="${change_domain_name}${change_domain_ttl}"
其他人是空的。所以,我不确定如何使用 jq --arg
简而言之,如果 domain_type=""或 domain_type 为空,我不希望这个变量在 --arg 选项中,所以用户可以选择不更新这个值。
最佳答案
最好使用像jq
这样的专用工具来构建JSON数据。 Bash 字符串构造是危险的。
#! /usr/bin/env bash
# hardcoded data for testing
declare LINODE_API_KEY=1234
declare domain_id=1931316
declare domain_name="abx.com"
declare domain_type="master"
declare domain_email="hello@abx.com"
declare domain_ttl=30
declare json_query_data='{}'
# This value must be provided first
if [ -z "${domain_name}" ]; then
echo "You must provide domain name"
exit 1
else
# shellcheck disable=SC2016
json_query_data=$(jq --arg domain "${domain_name}" '.domain |= $domain' <<<"${json_query_data}")
fi
if [ -n "${domain_type}" ]; then
# shellcheck disable=SC2016
json_query_data=$(jq --arg type "${domain_type}" '.type |= $type' <<<"${json_query_data}")
fi
if [ -n "${domain_email}" ]; then
# shellcheck disable=SC2016
json_query_data=$(jq --arg soa_email "${domain_email}" '.soa_email |= $soa_email' <<<"${json_query_data}")
fi
if [ -n "${domain_ttl}" ]; then
# shellcheck disable=SC2016
json_query_data=$(jq --argjson ttl_sec "${domain_ttl}" '.ttl_sec |= $ttl_sec' <<<"${json_query_data}")
fi
# Update the domain
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${LINODE_API_KEY}" \
-X PUT \
-d "${json_query_data}" \
--url "https://api.linode.com/v4/domains/${domain_id}"
cURL 命令是:
curl -H 'Content-Type: application/json' -H 'Authorization: Bearer 1234' -X PUT -d '{"domain":"abx.com","type":"master","soa_email":"hello@abx.com","ttl_sec":30}' --url 'https://api.linode.com/v4/domains/1931316'
关于json - 无法在 json --data 中使用变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74793913/