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 的注释:
...
- CLI 增强功能:
- 添加了四种新的输出模式:“box”、“json”、“markdown”和“table”。
- “列”输出模式会自动扩展列以包含最长的输出行,并自动打开“.header”(如果之前未设置)。
- “quote”输出模式遵循“.separator”
- CLI 内置了十进制扩展和 ieee754 扩展
...
如果您的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)
我想我更喜欢用每条记录一行来解析 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)