没有`jq`的情况下如何获取JSON字段值?

时间:2020-04-28 21:56:45

标签: json linux awk sed grep

我试图在有限的环境中从JSON提取值,在该环境中我无法安装任何工具或从Internet下载任何内容。我在环境上可用的工具是busybox提供的基本工具,例如:awkgrepsed。没有可用的编译器或解释器,例如Perl和Python。

我要解析的JSON具有固定的方案,但是可以用任何有效的方式对其进行格式化,而我始终需要获取字段tag的值。

可能的JSON示例:

{"version":1,"name":"2","tag":"3"}
{
    "version": 1,
    "tag":    "3",
    "name"   :"2"
}

2 个答案:

答案 0 :(得分:0)

这可能对您有用(GNU sed):

sed -nE '$!{:a;N;$!ba;s/\n//g;s/"tag":[^"]*"([^"]*)"/\n\1\nTAG/g};/^[^\n]*\nTAG/P;D' file

这会将文件插入到内存中,删除所有换行符,将标记值和标记反转到单独的连续行上,并打印这两行的第一行。

替代方式,使用trgrepsed

tr -d '\n' <file | grep -o '"tag":[^"]*"[^"]*"' | sed -E 's/".*".*"(.*)"/\1/'

答案 1 :(得分:0)

这将适用于您使用的数据格式(即不适用于可能的完整JSON语法),并且在每个UNIX框上的任何shell中使用任何awk:

$ cat tst.awk
{ rec = rec $0 }
END {
    gsub(/^[ \t]*[{][ \t]*|[ \t]*[}][ \t]*$/,"",rec)
    while ( match(rec,/"[^"]+"[ \t]*:[ \t]]*("[^"]*"|[^,]*)/) ) {
        key = val = substr(rec,RSTART+1,RLENGTH-1)
        sub(/".*/,"",key)
        sub(/[^"]*"[ \t]]*:[ \t]*/,"",val)
        f[key] = val
        rec = substr(rec,RSTART+RLENGTH)
    }
    print f[k]
}

$ echo '{"version":1,"name":"2","tag":"3"}' | awk -v k=tag -f tst.awk
"3"

$ cat file
{
    "version": 1,
    "tag":    "3",
    "name"   :"2"
}

$ awk -v k=tag -f tst.awk file
"3"

您可以轻松输出所需的任何值:

$ awk -v k=name -f tst.awk file
"2"

$ awk -v k=version -f tst.awk file
1

修改以任意顺序输出多个值是很简单的,或者仅在一个键的值在一定范围内或基于其他键值之间的关系等时才输出一个键的值。例如:

$ cat tst.awk
{ rec = rec $0 }
END {
    split(keys,ks,/,/)
    gsub(/^[ \t]*[{][ \t]*|[ \t]*[}][ \t]*$/,"",rec)
    while ( match(rec,/"[^"]+"[ \t]*:[ \t]*("[^"]*"|[^,]*)/) ) {
        key = val = substr(rec,RSTART+1,RLENGTH-1)
        sub(/".*/,"",key)
        sub(/[^"]*"[ \t]*:[ \t]*/,"",val)
        f[key] = val
        rec = substr(rec,RSTART+RLENGTH)
    }
    if ( (f["version"] > 0) && (f["name"] != f["tag"]) ) {
        for (i=1; i in ks; i++) {
            k = ks[i]
            print k, f[k]
        }
    }
}

$ awk -v keys=tag,version,name -f tst.awk file
tag "3"
version 1
name "2"

如果您不希望通过在gsub(/^"|"$/,"",val)上方的循环中仅添加f[key] = val来去除引号周围的引号,这也很简单。