Bash 变量替换为 json 字符串作为较大 json 对象中的变量

Bash 变量替换为 json 字符串作为较大 json 对象中的变量

我无法让 AWS cli 与 bash 变量正常工作。 AWS cli 命令接受 JSON 字符串作为参数。但是,在这个 json 字符串中,我使用的变量$SCHEMA_DEFINITION本身就是一个 JSON 字符串。由于某种原因,双引号被从$SCHEMA_DEFINITIONJSON 中删除并使其无效。如何保留这些引用并仍然生成有效的 AWS 命令​​?

aws glue create-schema --cli-input-json '{"RegistryId": {"RegistryName": "hxp-schema-registry"},"SchemaName": "'$modelClassName'","DataFormat": "AVRO","Compatibility": "FULL_ALL","SchemaDefinition": "'"$SCHEMA_DEFINITION"'"}'

给出错误:

An error occurred (InvalidInputException) when calling the CreateSchema operation: Schema definition of AVRO data format is invalid: Unexpected character ('n' (code 110)): was expecting double-quote to start field name
 at [Source: (String)"{name:hello}"

这是我设置变量的方法:SCHEMA_DEFINITION={"name":"Hello"}

答案1

您似乎想要创建的 JSON 应该包含一个编码为 JSON 字符串的 JSON 对象作为键的值SchemaDefinition。您似乎还想将 shell 变量的值modelClassName作为键的值包含在内SchemaName

jq您可以使用如下方式创建 JSON :

json=$(
    jq -n -c \
        --arg SchemaName "$modelClassName" \
        --arg SchemaDefinition '{"name": "Hello"}' \
        '{"RegistryId":{"RegistryName":"hxp-schema-registry"},"DataFormat":"AVRO","Compatibility":"FULL_ALL"} + $ARGS.named'
)

或者,为了更容易阅读,

json=$(
    jq -n -c \
        --arg SchemaName "$modelClassName" \
        --arg SchemaDefinition '{"name": "Hello"}' '
    {
      "RegistryId": {
        "RegistryName": "hxp-schema-registry"
      },
      "DataFormat": "AVRO",
      "Compatibility": "FULL_ALL"
    } + $ARGS.named'
)

甚至,

schema_json=$(
    jq -n -c --arg name 'hello' '$ARGS.named'
)

json=$(
    jq -n -c \
        --arg SchemaName "$modelClassName" \
        --arg SchemaDefinition "$schema_json" '
    {
      "RegistryId": {
        "RegistryName": "hxp-schema-registry"
      },
      "DataFormat": "AVRO",
      "Compatibility": "FULL_ALL"
    } + $ARGS.named'
)

这正确地将模式定义 JSON 对象和模型类名编码为 JSON 字符串,并将它们插入 JSON 文档中的适当位置。

然后调用你的命令:

aws glue create-schema --cli-input-json "$json"

答案2

外壳正在吃掉你的报价。引号对于 shell 来说是特殊的,它需要它们来保护其他特殊字符,例如空格:

$ var=aaa bb cc
bash: bb: command not found
terdon@tpad ~ $ var="aaa bb cc"
terdon@tpad ~ $ echo "$var"
aaa bb cc

因此,在您的情况下,外壳程序认为完全是为了保护该值,因此它不会将它们保存为变量值的一部分:

$ SCHEMA_DEFINITION={"name":"Hello"}
$ echo "$SCHEMA_DEFINITION"
{name:Hello}

但别担心,有一个简单的解决方法!您可以在变量定义周围使用单引号:

$ SCHEMA_DEFINITION='{"name":"Hello"}'
$ echo "$SCHEMA_DEFINITION"
{"name":"Hello"}

或者你可以逃避引号:

$ SCHEMA_DEFINITION={\"name\":\"Hello\"}
$ echo "$SCHEMA_DEFINITION"
{"name":"Hello"}

或者您可以使用printf内置命令:

$ printf -v SCHEMA_DEFINITION '{"%s":"%s"}' "name" "Hello"
$ echo "$SCHEMA_DEFINITION"
{"name":"Hello"}

或者您可以使用jo(1)公用事业:

SCHEMA_DEFINITION=$(jo name=hello)

我什至建议首先将整个事物构建为变量:

schema_definition='{"name":"Hello"}'
modelClassName='"thisModel"'
json_string='{"RegistryId": {"RegistryName": "hxp-schema-registry"},"SchemaName":'
json_string="$json_string $modelClassName"
json_string="$json_string"' "DataFormat": "AVRO","Compatibility": "FULL_ALL","SchemaDefinition": '"$schema_definition"

结果是:

$ echo "$json_string"
{"RegistryId": {"RegistryName": "hxp-schema-registry"},"SchemaName": "thisModel" "DataFormat": "AVRO","Compatibility": "FULL_ALL","SchemaDefinition": {"name":"Hello"}

所以你现在可以这样做:

aws glue create-schema --cli-input-json "$json_string"

答案3

Terdon 是对的,您的 json 变量设置不正确,但您也错误地将其传递给命令。

您正在通过:

{
    "RegistryId": {
        "RegistryName": "hxp-schema-registry"
    },
    "SchemaName": "'$modelClassName'",
    "DataFormat": "AVRO",
    "Compatibility": "FULL_ALL",
    "SchemaDefinition": "'"$SCHEMA_DEFINITION"'"
}

这将扩展到:

{
    "RegistryId": {
        "RegistryName": "hxp-schema-registry"
    },
    "SchemaName": "'$modelClassName'",
    "DataFormat": "AVRO",
    "Compatibility": "FULL_ALL",
    "SchemaDefinition": "{"name":"Hello"}"
}

特别注意"{"name":"Hello"}"

我建议为此使用heredoc,但无论哪种方式,您都需要删除{}.

read -rd json <<EOF
{
    "RegistryId": {
        "RegistryName": "hxp-schema-registry"
    },
    "SchemaName": "$modelClassName",
    "DataFormat": "AVRO",
    "Compatibility": "FULL_ALL",
    "SchemaDefinition": $SCHEMA_DEFINITION
}
EOF

或者使用 jo(1):

json=$(jo RegistryId=$(jo RegistryName=hxp-schema-registry) \
SchemaName=$modelClassName \
DataFormat=AVRO \
Compatibility=FULL_ALL \
SchemaDefinition=$SCHEMA_DEFINITION)

然后你可以用一个变量调用你的命令:

aws glue create-schema --cli-input-json "$json"

我还推荐https://jsonlint.com/如果您遇到这样的问题,请验证您的 json 输入。

相关内容