为什么来自 heredoc 的 JSON 内容无法解析?

Jim*_*Jim 15 shell here-document variable json

我有一个 JSON 片段。

以下不起作用:

VALUE=<<PERSON
{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "jim@gmail.com"  
}
PERSON
echo -n "$VALUE" | python -m json.tool
Run Code Online (Sandbox Code Playgroud)

结果是:

无法解码 JSON 对象

做同样的事情jq,即

echo -n "$VALUE" | jq '.'
Run Code Online (Sandbox Code Playgroud)

没有输出。

以下行为具有相同的行为:

VALUE=<<PERSON
'{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "jim@gmail.com"  
}'
PERSON
echo -n "$VALUE" | python -m json.tool
Run Code Online (Sandbox Code Playgroud)

回复:

无法解码 JSON 对象

但以下工作:

VALUE='{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "jim@gmail.com"
}'
echo -n "$VALUE" | jq '.'
echo -n "$VALUE" | python -m json.tool
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 21

VALUE=<<PERSON
some data
PERSON

echo "$VALUE"
Run Code Online (Sandbox Code Playgroud)

没有输出。

一个 here-document 是一个重定向,你不能重定向到一个变量。

解析命令行时,重定向在与变量分配不同的步骤中处理。因此,您的命令等效于(注意空格)

VALUE= <<PERSON
some data
PERSON
Run Code Online (Sandbox Code Playgroud)

也就是说,它为您的变量分配一个空字符串,然后将标准输入从 here-string 重定向到命令中(但没有命令,所以什么也没有发生)。

注意

<<PERSON
some data
PERSON
Run Code Online (Sandbox Code Playgroud)

是有效的

<somefile
Run Code Online (Sandbox Code Playgroud)

只是没有命令的标准输入流可以设置为包含数据,所以它只是丢失了。

这虽然有效:

VALUE=$(cat <<PERSON
some data
PERSON
)
Run Code Online (Sandbox Code Playgroud)

在这里,接收 here-document 的命令是cat,并将其复制到其标准输出。这就是通过命令替换分配给变量的内容。

在您的情况下,您可以改为使用

python -m json.tool <<END_JSON
JSON data here
END_JSON
Run Code Online (Sandbox Code Playgroud)

无需采取将数据存储在变量中的额外步骤。


研究jo使用正确编码创建 JSON 数据之类的工具也可能是值得的:

例如:

jo type=account customer_id=1234 customer_email=jim@gmail.com random_data="some^Wdata"
Run Code Online (Sandbox Code Playgroud)

... where^W是一个文字Ctrl+W字符,会输出

{"type":"account","customer_id":1234,"customer_email":"jim@gmail.com","random_data":"some\u0017data"}
Run Code Online (Sandbox Code Playgroud)

所以问题中的命令可以写成

jo type=account customer_id=1234 customer_email=jim@gmail.com |
python -m json.tool
Run Code Online (Sandbox Code Playgroud)

  • 你也可以只做`PERSON="`,然后是一个换行符和多行数据,然后是另一个`"`。 (2认同)
  • @R .. 鉴于我们谈论的是 JSON,最好使用单引号不必转义每个属性名称的双引号。`人=`。除非 OP 想稍后插入变量。 (2认同)

ter*_*don 12

因为变量不是由您的 heredoc 设置的:

$ VALUE=<<PERSON  
> {    
>   "type": "account",  
>   "customer_id": "1234",  
>   "customer_email": "jim@gmail.com",  
> }  
> PERSON
$ echo "$VALUE" 

$
Run Code Online (Sandbox Code Playgroud)

如果要使用 heredoc 为变量赋值,则需要类似以下内容:

$ read -d '' -r VALUE <<PERSON  
{    
  "type": "account",  
  "customer_id": "1234",  
  "customer_email": "jim@gmail.com",  
}   
PERSON
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。`$(cat &lt;&lt;EOF ... EOF)` 是一个奇怪的结构:运行一个子shell,然后将一个heredoc发送给cat,这样它就将它发送到STDOUT,然后将该子shell的结果分配给一个变量?我希望人们会考虑_他们在说什么_他们的思维过程。相比之下,通过 `read` 将一个 heredoc 分配给一个变量是明智的。 (3认同)

Ini*_*ian 5

这是因为您定义 here-doc 以与 JSON 一起使用的方式是错误的。您需要将其用作

VALUE=$(cat <<EOF
{  
  "type": "account",  
  "customer_id": "1234",  
  "customer_email": "jim@gmail.com",  
}
EOF
)
Run Code Online (Sandbox Code Playgroud)

并且这样做printf "$VALUE"应该按预期转储JSON。