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

Pat*_*ren 2 sqlite bash awk grep json

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

我想用这个语法:

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

OUTPUT:

      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
Run Code Online (Sandbox Code Playgroud)

如何在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
  }
}
Run Code Online (Sandbox Code Playgroud)

roj*_*jen 10

-json只需使用 SQLite 3.33.0 或更高版本输入参数即可获得 json 输出:

$ sqlite3 -json database.db "select * from TABLE_NAME"
Run Code Online (Sandbox Code Playgroud)

来自 SQLite 版本 3.33.0 的注释:

...

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

...


pea*_*eak 9

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

select json_object('id', id, 'fname', fname, 'gname', gname, 'genderid', genderid) ...
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用诸如jq之类的工具将对象流转换为对象数组,例如将sqlite3的输出传递给jq -s ..

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

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

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 "]"} '
Run Code Online (Sandbox Code Playgroud)

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

  def trim: sub("^ *"; "") | sub(" *$"; "");
  def keyvalue: index("=") as $i 
    | {(.[0:$i] | trim): (.[$i+2:] | (tonumber? // .))};
  [foreach (inputs, "") as $line ({object: false, seed: {} };
     if ($line|trim) == "" then { object: .seed, seed : {} }
     else {object: false, 
           seed: (.seed + ($line | keyvalue)) }
     end;
     .object | if . and (. != {}) then . else empty end ) ]
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 5

我想我更喜欢用每条记录一行来解析 sqlite 输出,而不是您建议的非常冗长的输出格式sqlite3 -line。所以,我会这样:

sqlite3 members.db "SELECT * FROM members LIMIT 3"
Run Code Online (Sandbox Code Playgroud)

这让我可以解析:

1|Leif|Hakansson|1
2|Yvonne|Bergman|2
3|Roger|Sjoberg|1
Run Code Online (Sandbox Code Playgroud)

awk如果我将输入分隔符设置为|with ,我现在可以解析它

awk -F '|'
Run Code Online (Sandbox Code Playgroud)

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

{ id[++i]=$1; fname[i]=$2; gname[i]=$3; genderid[i]=$4 }
Run Code Online (Sandbox Code Playgroud)

然后我需要做的就是在最后打印你需要的输出格式。但是,输出中有双引号,并且在 中引用它们很麻烦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 '|' '"'
Run Code Online (Sandbox Code Playgroud)