How to format a bash array as a JSON array

后端 未结 5 933
醉酒成梦
醉酒成梦 2021-01-02 05:02

I have a bash array

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

That I want to turn into a json array

[\"hello world\", \"goodni         


        
相关标签:
5条回答
  • 2021-01-02 05:17

    You can do this:

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

    output

    [
      "hello world",
      "goodnight moon"
    ]
    
    0 讨论(0)
  • 2021-01-02 05:20

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

    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
    > x = ["hello\ world","goodnight\ moon","say\ \"boo\"","foo\\bar"]
    [ 'hello world',
      'goodnight moon',
      'say "boo"',
      'foo\\bar' ]
    
    0 讨论(0)
  • 2021-01-02 05:28

    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 any subprocess is likely to your advantage.

    0 讨论(0)
  • 2021-01-02 05:28

    You can use:

    X=("hello world" "goodnight moon")
    sed 's/^/[/; s/,$/]/' <(printf '"%s",' "${X[@]}") | jq -s '.'
    [
      [
        "hello world",
        "goodnight moon"
      ]
    ]
    
    0 讨论(0)
  • 2021-01-02 05:31

    If the values do not contain ASCII control characters, which have to be escaped in strings in valid JSON, you can also use 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:

    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
    
    0 讨论(0)
提交回复
热议问题