请不要使用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{}。