如何将 bash 数组格式化为 JSON 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26808855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:45:22  来源:igfitidea点击:

How to format a bash array as a JSON array

arraysjsonbashjq

提问by Jon

I have a bash array

我有一个 bash 数组

X=("hello world" "goodnight moon")

That I want to turn into a json array

我想变成一个 json 数组

["hello world", "goodnight moon"]

Is there a good way for me to turn this into a json array of strings without looping over the keys in a subshell?

有没有什么好方法可以将它转换为字符串的 json 数组,而无需在子 shell 中遍历键?

(for x in "${X[@]}"; do; echo $x | sed 's|.*|"&"|'; done) | jq -s '.'

This clearly doesn't work

这显然不起作用

echo "${X[@]}" | jq -s -R '.'

回答by kev

You can do this:

你可以这样做:

X=("hello world" "goodnight moon")
printf '%s\n' "${X[@]}" | jq -R . | jq -s .

output

输出

[
  "hello world",
  "goodnight moon"
]

回答by John Bollinger

This ...

这个 ...

X=("hello world" "goodnight moon" 'say "boo"' 'foo\bar')

json_array() {
  echo -n '['
  while [ $# -gt 0 ]; do
    x=${1//\/\\}
    echo -n \"${x//\"/\\"}\"
    [ $# -gt 1 ] && echo -n ', '
    shift
  done
  echo ']'
}

json_array "${X[@]}"

... yields:

...产量:

["hello world", "goodnight moon", "say \"boo\"", "foo\bar"]

If you are planning to do a lot of this (as your reluctance to use a subshell suggests) then something such as this that does not rely on anysubprocess is likely to your advantage.

如果您打算做很多这样的事情(正如您不愿使用子shell 所暗示的那样),那么诸如此类的不依赖于任何子进程的事情可能对您有利。

回答by nisetama

If the values do not contain ASCII control characters, which have to be escaped in strings in valid JSON, you can also use sed:

如果值不包含 ASCII 控制字符,这些字符必须在有效 JSON 的字符串中转义,您还可以使用sed

$ X=("hello world" "goodnight moon")
$ printf %s\n "${X[@]}"|sed 's/["\]/\&/g;s/.*/"&"/;1s/^/[/;$s/$/]/;$!s/$/,/'
["hello world",
"goodnight moon"]

If the values contain ASCII control characters, you can do something like this:

如果值包含 ASCII 控制字符,您可以执行以下操作:

X=($'a\ta' $'a\n\\"')
for((i=0;i<${#X[@]};i++));do
  [ $i = 0 ]&&printf \[
  printf \"
  e=${X[i]}
  e=${e//\/\\}
  e=${e//\"/\\"}
  for((j=0;j<${#e};j++));do
    c=${e:j:1}
    if [[ $c = [[:cntrl:]] ]];then
      printf '\u%04x' "'$c"
    else
      printf %s "$c"
    fi
  done
  printf \"
  if((i<=${#X[@]}-2));then
    printf ,
  else
    printf \]
  fi
done

回答by anubhava

You can use:

您可以使用:

X=("hello world" "goodnight moon")
sed 's/^/[/; s/,$/]/' <(printf '"%s",' "${X[@]}") | jq -s '.'
[
  [
    "hello world",
    "goodnight moon"
  ]
]

回答by glenn Hymanman

If you're OK with a few extra backslashes, bash's printf "%q"is useful:

如果您可以使用一些额外的反斜杠,那么 bashprintf "%q"很有用:

X=("hello world" "goodnight moon" 'say "boo"' 'foo\bar')
json="[$(printf '"%q",' "${X[@]}")"
json="${json%,}]"
echo "$json"
["hello\ world","goodnight\ moon","say\ \"boo\"","foo\bar"]


Regarding the OK-ness of the backslashes: node.js doesn't have a problem with them:

关于反斜杠的正常性:node.js 没有问题:

$ node
> x = ["hello\ world","goodnight\ moon","say\ \"boo\"","foo\bar"]
[ 'hello world',
  'goodnight moon',
  'say "boo"',
  'foo\bar' ]