Shell while 循环到 JSON

Shell while loop to JSON

我有一个带有两个变量的 while 循环,我必须将其合并到一个 JSON 中,像这样:

#!/bin/bash
while read -r from to
do
    # BONUS: Solution would ideally require no quoting at this point
    echo { \"From\": \"$from\", \"To\": \"$to\" } 
done << EOF
foo bar
what ever
EOF

当前输出无效JSON:

{ "From": "foo", "To": "bar" }
{ "From": "what", "To": "ever" }

我可以创建有效的 JSON 最简单的方法是:

[
{ "From": "foo", "To": "bar" },
{ "From": "what", "To": "ever" }
]

我看了 jq 但我不知道该怎么做。我不是 理想的,因为我觉得添加逗号有点难看。

与 jq:

$ jq -nR '[inputs | split(" ") | {"From": .[0], "To": .[1]}]' <<EOF
foo bar
what ever
EOF

[
  {
    "From": "foo",
    "To": "bar"
  },
  {
    "From": "what",
    "To": "ever"
  }
]

-n 告诉 jq 不读取任何输入; -R 用于原始输入,因此它不期望 JSON.

使用 inputs 读取输入,导致每个输入行一个字符串:

$ jq -nR 'inputs' <<EOF
foo bar
what ever
EOF
"foo bar"
"what ever"

然后将这些拆分为单词数组:

$ jq -nR 'inputs | split(" ")' <<EOF
foo bar
what ever
EOF

[
  "foo",
  "bar"
]
[
  "what",
  "ever"
]

据此,我们构造对象:

$ jq -nR 'inputs | split(" ") | {"From": .[0], "To": .[1]}' <<EOF
foo bar
what ever
EOF

{
  "From": "foo",
  "To": "bar"
}
{
  "From": "what",
  "To": "ever"
}

最后,我们将所有内容包装在 [] 中以首先显示最终输出。

直接拆分输入的更直观方法失败了,因为将所有内容包装在 [] 中会导致每个输入行一个数组:

$ jq -R '[split(" ") | { "From": .[0], "To": .[1] }]' <<EOF
foo bar
what ever
EOF

[
  {
    "From": "foo",
    "To": "bar"
  }
]
[
  {
    "From": "what",
    "To": "ever"
  }
]

因此有点麻烦-n/inputs。请注意,inputs 需要 jq 版本 1.5。

这是一个全 jq 解决方案,假设 "From" 和 "To" 值与您的示例中的值完全相同:

jq -R -n '[inputs | split(" ") | {From: .[0], To: .[1]}]'

您可能希望使用 gsub/2 来处理额外的空格。

如果你的jq没有inputs那么你可以用这个咒语:

jq -R -s 'split("\n")
  | map(select(length>1) | split(" ") | {From: .[0], To: .[1]})'

或者您可以将 while 循环的输出通过管道传输到 jq -s