简体   繁体   English

如何在没有“jq”的情况下获得 JSON 字段值?

[英]How can I get a JSON field value without `jq`?

I'm trying to extract a value from a JSON in a limited environment where I cannot install any tools or download anything from the internet.我试图在有限的环境中从 JSON 中提取一个值,在该环境中我无法安装任何工具或从 Internet 下载任何内容。 The tools that I have available on the environment are the basic ones provided by busybox such as: awk , grep , and sed .我在环境中可用的工具是busybox提供的基本工具,例如: awkgrepsed No compilers or interpreters like Perl and Python are available.没有像 Perl 和 Python 这样的编译器或解释器可用。

The JSON I'm trying to parse has a fixed scheme but it can be formatted in any valid way and I always need to get the value of the field tag .我试图解析的 JSON 有一个固定的方案,但它可以以任何有效的方式格式化,我总是需要获取字段tag的值。

Examples of possible JSONs:可能的 JSON 示例:

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

This might work for you (GNU sed):这可能对您有用(GNU sed):

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

This slurps the file into memory, removes all newlines, reverses tag value and tag onto separate consecutive lines and prints the first of those two lines.这会将文件插入 memory,删除所有换行符,将标签值和标签反转到单独的连续行并打印这两行中的第一行。

Alternative, using tr , grep and sed :或者,使用trgrepsed

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

This will work for the data format you have (ie not for the possible full JSON syntax) using any awk in any shell on every UNIX box: This will work for the data format you have (ie not for the possible full JSON syntax) using any awk in any shell on every UNIX box:

$ 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"

You can easily output whatever value you like:您可以轻松地 output 任何您喜欢的值:

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

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

and it'd be trivial to modify to output multiple values in any order you like, or only output the value of one key if it's in a range or based on relationships between other keys values, etc., etc. For example:并且以您喜欢的任何顺序将多个值修改为 output 或仅 output 一个键的值(如果它在一个范围内或基于其他键值之间的关系等)将是微不足道的。例如:

$ 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"

It'd also be trivial to strip the quotes from around the values if you don't want them by just adding gsub(/^"|"$/,"",val) in the loop right above f[key] = val .如果您不想要它们,只需在f[key] = val正上方的循环中添加gsub(/^"|"$/,"",val)从值周围去除引号也很简单.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM