Bash sqlite3 -line |如何转换为JSON格式

时间:2016-03-16 22:40:57

标签: json bash awk sqlite grep

我想将我的sqlite数据从我的数据库转换为JSON格式。

我想使用这种语法:

sqlite3 -line members.db“SELECT * FROM members LIMIT 3”> members.txt

输出:

      id = 1
   fname = Leif
   gname = Håkansson
genderid = 1

      id = 2
   fname = Yvonne
   gname = Bergman
genderid = 2

      id = 3
   fname = Roger
   gname = Sjöberg
genderid = 1

如何在for循环中使用nice和structur代码执行此操作? (仅限Bash)

我尝试了一些awk和grep,但还没有取得很大的成功。

一些提示会很好。

我想要一个与此类似的结果:

[
  {
    "id":1,
    "fname":"Leif",
    "gname":"Hakansson",
    "genderid":1
  },
  {
    "id":2,
    "fname":"Yvonne",
    "gname":"Bergman",
    "genderid":2
  },
  {
    "id":3,
    "fname":"Roger",
    "gname":"Sjberg",
    "genderid":1
  }
}

6 个答案:

答案 0 :(得分:8)

如果您的sqlite3是使用json1扩展编译的(或者如果您可以获得带有json1扩展名的sqlite3版本),那么您可以使用它来生成JSON对象(每行一个JSON对象)。例如:

$(".buttons").click(function() {
    var div = $("<div/>");
    var offset = $(this).offset();
    var posx = event.pageX - offset.left;
    var posy = event.pageY - offset.top;
    div.addClass("ripple");
    div.css({
        "width": $(this).width,
        "height": $(this).height,
        "top": posy,
        "left": posx,
        "background": $(this).data("ripple_color"),
    }).appendTo($(this));
    setTimeout(function() {
        div.remove();
    }, 1500);
});

然后,您可以使用jq之类的工具将对象流转换为对象数组,例如将sqlite3的输出传递给select json_object('id', id, 'fname', fname, 'gname', gname, 'genderid', genderid) ...

(一个不太烦人的替代方案可能是使用sqlite3函数json_array(),它生成一个数组,你可以使用jq将其重组为一个对象。)

如果json1扩展名不可用,那么您可以使用以下内容作为起点:

jq -s .

或者,您可以使用以下jq脚本,该脚本将RHS上出现的数字字符串“=”转换为数字:

awk 'BEGIN { print "["; } 
 function out() {if (n++) {print ","}; if (line) {print "{" line "}"}; line="";}
 function trim(x) { sub(/^ */, "", x); sub(/ *$/, "", x); return x; }
 NF==0 { out(); next}; 
 {if (line) {line = line ", " }
  i=index($0,"="); 
  line = line "\"" trim(substr($0,1,i-1)) ": \"" substr($0, i+2) "\""}
 END {out(); print "]"} '

答案 1 :(得分:2)

我认为我更倾向于使用每条记录一行来解析sqlite输出,而不是使用sqlite3 -line建议的非常冗长的输出格式。所以,我会这样做:

sqlite3 members.db "SELECT * FROM members LIMIT 3"

这让我解析:

1|Leif|Hakansson|1
2|Yvonne|Bergman|2
3|Roger|Sjoberg|1

如果我使用

将输入分隔符设置为awk,我现在可以使用|解析该问题
awk -F '|'

并使用以下内容拾取每行上的4个字段,并将它们保存在如下数组中:

{ id[++i]=$1; fname[i]=$2; gname[i]=$3; genderid[i]=$4 }

然后我需要做的就是打印最后需要的输出格式。但是,你的输出中有双引号,在awk引用它们很难,所以我暂时使用另一个管道符号(|)作为双引号然后,最后,我得到tr用双引号替换所有管道符号 - 只是为了使代码更容易。所以整个解决方案看起来像这样:

sqlite3 members.db "SELECT * FROM members LIMIT 3" | awk -F'|' '
   # sqlite output line - pick up fields and store in arrays
   { id[++i]=$1; fname[i]=$2; gname[i]=$3; genderid[i]=$4 }

   END {
      printf "[\n";
      for(j=1;j<=i;j++){
         printf "  {\n"
         printf "    |id|:%d,\n",id[j]
         printf "    |fname|:|%s|,\n",fname[j]
         printf "    |gname|:|%s|,\n",gname[j]
         printf "    |genderid|:%d\n",genderid[j]
         closing="  },\n"
         if(j==i){closing="  }\n"}
         printf closing;
      }
      printf "]\n";
   }' | tr '|' '"'

答案 2 :(得分:1)

只需在 SQLite 3.33.0 或更高版本中输入 -json 参数并获得 json 输出:

$ sqlite3 -json database.db "select * from TABLE_NAME"

来自 SQLite Release 3.33.0 注意:

<块引用>

...

  1. CLI 增强功能:
  • 添加了四种新的输出模式:“box”、“json”、“markdown”和“table”。
  • “列”输出模式会自动扩展列以包含最长的输出行并自动打开“.header”(如果有) 之前未设置。
  • “quote”输出模式尊重“.separator”
  • CLI 内置了十进制扩展和 ieee754 扩展

...

答案 3 :(得分:0)

总比不插入jo迟。

将sqlite3保存到文本文件。

获取jo(jo也在发行版存储库中可用)

并使用此bash脚本。

while read line
do 
    id=`echo $line | cut -d"|" -f1`
    fname=`echo $line | cut -d"|" -f2`
    gname=`echo $line | cut -d"|" -f3`
    genderid=`echo $line | cut -d"|" -f4`
    jsonline=`jo id="$id" fname="$fname" gname="$gname" genderid="$genderid"`
    json="$json $jsonline"
done < "$1"

jo -a $json

答案 4 :(得分:0)

Sqlite-utils 完全符合您的要求。默认情况下,输出将为 JSON。

答案 5 :(得分:-1)

请不要使用awk创建(或解析)json。为此有专用工具。 xidel之类的工具。
首先,最重要的是html,xml和json解析器,xidel也可以解析纯文本。

我想使用此工具提供一个非常优雅的解决方案(代码比jq少得多)。
我假设您的'members.txt'

首先为每个要创建的json对象创建一个序列:

xidel -s members.txt --xquery 'tokenize($raw,"\n\n")'

或者...

xidel -s members.txt --xquery 'tokenize($raw,"\n\n") ! (position(),.)'
1
      id = 1
   fname = Leif
   gname = Håkansson
genderid = 1
2
      id = 2
   fname = Yvonne
   gname = Bergman
genderid = 2
3
      id = 3
   fname = Roger
   gname = Sjöberg
genderid = 1

...以便更好地向您展示序列中的各个项目。

现在您有3个多行字符串。要将每个项目/字符串转换为另一个序列,其中每个项目都是新行:

xidel -s members.txt --xquery 'tokenize($raw,"\n\n") ! x:lines(.)'

({x:lines(.)tokenize(.,'\r\n?|\n')的简写)

现在,每行标记“ =”(这会创建另一个序列)并将其保存到变量中。例如,对于第一行,此序列为("id","1"),对于第二行,{序列为("fname","Leif"),依此类推:

xidel -s members.txt --xquery 'tokenize($raw,"\n\n") ! (for $x in x:lines(.) let $a:=tokenize($x," = ") return ($a[1],$a[2]))'

最后删除前导空格(normalize-space()),创建json对象({| {key-value-pair} |})并将所有json对象放入数组([ ... ]):

xidel -s members.txt --xquery '[tokenize($raw,"\n\n") ! {|for $x in x:lines(.) let $a:=tokenize($x," = ") return {normalize-space($a[1]):$a[2]}|}]'

美化+输出:

xidel -s members.txt --xquery '
  [
    tokenize($raw,"\n\n") ! {|
      for $x in x:lines(.)
      let $a:=tokenize($x," = ")
      return {
        normalize-space($a[1]):$a[2]
      }
    |}
  ]
'
[
  {
    "id": "1",
    "fname": "Leif",
    "gname": "Håkansson",
    "genderid": "1"
  },
  {
    "id": "2",
    "fname": "Yvonne",
    "gname": "Bergman",
    "genderid": "2"
  },
  {
    "id": "3",
    "fname": "Roger",
    "gname": "Sjöberg",
    "genderid": "1"
  }
]

注意:对于xidel-0.9.9.7173和更高版本的--json-mode=deprecated,需要使用[ ]创建一个json数组。创建json数组的新(XQuery 3.1)方法是使用array{ }