如何用jq替换json文件中的值? DRY-er

问题描述

我有一个具有以下结构的json

[{
    "model": "about.term","pk": 20202,"fields": {
        "term": "Summer","year": 2020
    }
},{
    "model": "about.term","pk": 20203,"fields": {
        "term": "Fall",{
    "model": "about.officer","pk": 1,"fields": {
        "position": "President","term_position_number": 0,"name": "Person 1","start_date": "1984-01-01T00:00:00","sfuid": "","sfu_email_alias": "","phone_number": 11111111111,"github_username": "","gmail": "","course1": "","course2": "","language1": "","language2": "","bio": "","image": "about_static/exec-photos/stockPhoto.jpg","elected_term": 19841,"sfu_officer_mailing_list_email": "NONE"
    }
},"pk": 2,"fields": {
        "position": "Vice President","term_position_number": 1,"name": "Person 2","phone_number": 2222222222222,"pk": 3,"fields": {
        "position": "Treasurer","term_position_number": 2,"name": "Person 3","phone_number": 3333333333,"pk": 4,"fields": {
        "position": "Secretary","term_position_number": 3,"name": "Person 4","phone_number": 444444444444,"sfu_officer_mailing_list_email": "NONE"
    }
}]

如何使用bash jq命令对其进行更改,使其具有完全相同的数据,结构和缩进,但是键sfuid的值变为sfuidsfu_email_alias成为sfu_email_aliasphone_number成为0github_username成为github_usernamegmail成为gmail

基本上,我想结束这个文件

[{
    "model": "about.term","sfuid": "sfuid","sfu_email_alias": "sfu_email_alias","phone_number": 0,"github_username": "github_username","gmail": "gmail","sfu_officer_mailing_list_email": "NONE"
    }
}]

解决方法

假设输入是有效JSON,并且可接受的有效JSON作为输出, 以下jq程序将执行所需的转换:

map( reduce ("sfuid","sfu_email_alias","github_username","gmail") as $k (.;
         if .fields[$k] then .fields[$k] = $k else . end)
       | if .fields.phone_number then .fields.phone_number = 0 else . end )

在这里使用reduce当然是支持“ DRY”的。如果您不熟悉reduce,则可以将其视为一种for循环。

DRY-er

def update($PATH; VALUE):
  . as $in
  | if ($PATH | select(IN($in|paths)) // null) 
    then setpath($PATH;VALUE) else . end;

map( reduce ("sfuid","gmail") as $k (.;
         update( ["fields",$k]; $k )
       | update( ["fields","phone_number"]; 0) ))