简体   繁体   English

匹配JSON文本中的键值模式并获取另一个键的值

[英]Match a key-value pattern in JSON text and get the value for another key

Suppose I have a file with this JSON: 假设我有一个带有此JSON的文件:

[
   {
      "label" : "deploy",
      "pk" : 2388175,
      "key" : "gsfd45"
   },
   {
      "label" : "jenkins",
      "key" : "eQtIAwP",
      "pk" : 2388165
   }
]

I want to get the value for key "pk" if it is in the hash that has label = "deploy". 我想获取键“ pk”的值,如果它在具有label =“ deploy”的哈希中。

How can I do this? 我怎样才能做到这一点? Do I need to write a script? 我需要写脚本吗?

To parse JSON in Bash, use jq ! 要在Bash中解析JSON,请使用jq

$ jq '.[] | select(.label=="deploy").pk' file
2388175

If you want to store deploy in a variable, use --arg . 如果要将deploy存储在一个变量中,请使用--arg From jq manual → Invoking jq : jq手册→调用jq

--arg name value --arg名称值

This option passes a value to the jq program as a predefined variable. 此选项将值作为预定义变量传递给jq程序。 If you run jq with --arg foo bar, then $foo is available in the program and has the value "bar". 如果使用--arg foo bar运行jq,则$ foo在程序中可用,并且值为“ bar”。 Note that value will be treated as a string, so --arg foo 123 will bind $foo to "123". 请注意,值将被视为字符串,因此--arg foo 123会将$ foo绑定到“ 123”。

$ v="deploy"
$ jq --arg var "$v" '.[] | select(.label==$var).pk' file
2388175

$ v="blabla"
$ jq --arg var "$v" '.[] | select(.label==$var).pk' file
            # empty!

$ v="jenkins"
$ jq --arg var "$v" '.[] | select(.label==$var).pk' file
2388165

By pieces: 按件:

Print everything: 打印所有内容:

$ jq '.[]' file
{
  "key": "gsfd45",
  "pk": 2388175,
  "label": "deploy"
}
{
  "pk": 2388165,
  "key": "eQtIAwP",
  "label": "jenkins"
}

Print those records where label equals "deploy": 打印label等于“ deploy”的记录:

$ jq '.[] | select(.label=="deploy")' file
{
  "key": "gsfd45",
  "pk": 2388175,
  "label": "deploy"
}

Print just the field pk in such case: 在这种情况下,只打印字段pk

$ jq '.[] | select(.label=="deploy").pk' file
2388175

If jq was not availale on your server, python should be there, right? 如果您的服务器上没有jq,则python应该在那里,对吗? ^_* ^ _ *

#!/bin/python
import json
with open('data.json') as data_file:    
    data = json.load(data_file)
    for d in data:
        if d['label'] == 'deploy':
            print(d["pk"])

assume your file named as data.json save it as id.py , and run with: 假定名为data.json的文件另存为id.py ,并运行:

python id.py

It needs python3 installed on your system. 它需要在系统上安装python3

change the line print (d["pk"]) into print d["pk"] if you only have python2 installed. 如果仅安装了python2,则将行print (d["pk"])更改为print d["pk"]

The output would be: 输出为:

2388175

Edit 编辑

added the if check, didn't notice OP wanted to check the label . 添加了if检查,没有注意到OP要检查label

In awk. 在awk。 It's a bit incomplete but as you didn't have anything to show, you can work on this one: 这有点不完整,但是由于您没有任何要显示的内容,因此可以进行以下操作:

$ awk -F: '$1~/"label"/{l=$2} l~/deploy/ && $1 ~ /pk/ {sub(/,/,"",$2);print $2}' file
 2388175

When awk meets a record with "label" on it, it stores the $2 . 当awk遇到上面带有"label"的记录时,它将存储$2 Once the pk is found and flag l has deploy in it, remove comma and print. 一旦找到pk并在其中deploy了标记l ,请删除逗号并打印。

If the elegant solution provided by James Brown does not work (eg different ordering of the key/value pairs) here is something that tries to get at least the string between the braces into one record (by setting RS ), then the string is splittet at the key value pair with key "pk" (by setting FS ). 如果James Brown提供的优雅解决方案不起作用(例如,键/值对的不同顺序),则是尝试至少将大括号之间的字符串合并为一个记录(通过设置RS ),然后将字符串拆分在具有键“ pk”的键值对中(通过设置FS )。

After that setup the pattern looks for the label/deploy key/value pair in $0 and then, only if there are two fields (eg the pk was present and a field split took place) the string after the comma in $2 is deleted and the value of key pk remains and is printed: 完成该设置后,模式将在$ 0中查找标签/部署键/值对,然后,仅当有两个字段(例如pk存在且发生字段拆分)时,才会删除$ 2中逗号后的字符串,并密钥pk的值保留并打印:

script.awk script.awk

BEGIN {
    RS="[{}[\\]]"
    FS="\"pk\"[^:]*:"
    }

/"label"[^:]*:[^\"]*"deploy"/ {
        if( NF == 2 ) { 
            # "pk" is present in $0, remove everything after comma
            sub(/,.*/, "", $2)
            print $2
        }
    }

You use this script with awk like this: awk -f script.awk yourfile . 您可以将以下脚本与awk一起使用: awk -f script.awk yourfile

I have only tried it with GNU awk, but RS and FS should also work with awk, too. 我只在GNU awk上进行过尝试,但是RSFS也应在awk上运行。

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

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