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
。
我有一个带有两个变量的 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
。