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

how to replace a value in a json file with jq?

我有一个 json 具有以下结构

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

如何使用 bash jq 命令更改它,使其具有完全相同的数据、结构和缩进,但键 sfuid 的值变为 sfuid , sfu_email_alias 变为 sfu_email_alias, phone_number 变为 0, github_username 变为 github_username 并且 gmail 变为 gmail.

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

[{
    "model": "about.term",
    "pk": 20202,
    "fields": {
        "term": "Summer",
        "year": 2020
    }
},
{
    "model": "about.term",
    "pk": 20203,
    "fields": {
        "term": "Fall",
        "year": 2020
    }
},
{
    "model": "about.officer",
    "pk": 1,
    "fields": {
        "position": "President",
        "term_position_number": 0,
        "name": "Person 1",
        "start_date": "1984-01-01T00:00:00",
        "sfuid": "sfuid",
        "sfu_email_alias": "sfu_email_alias",
        "phone_number": 0,
        "github_username": "github_username",
        "gmail": "gmail",
        "course1": "",
        "course2": "",
        "language1": "",
        "language2": "",
        "bio": "",
        "image": "about_static/exec-photos/stockPhoto.jpg",
        "elected_term": 19841,
        "sfu_officer_mailing_list_email": "NONE"
    }
},
{
    "model": "about.officer",
    "pk": 2,
    "fields": {
        "position": "Vice President",
        "term_position_number": 1,
        "name": "Person 2",
        "start_date": "1984-01-01T00:00:00",
        "sfuid": "sfuid",
        "sfu_email_alias": "sfu_email_alias",
        "phone_number": 0,
        "github_username": "github_username",
        "gmail": "gmail",
        "course1": "",
        "course2": "",
        "language1": "",
        "language2": "",
        "bio": "",
        "image": "about_static/exec-photos/stockPhoto.jpg",
        "elected_term": 19841,
        "sfu_officer_mailing_list_email": "NONE"
    }
},
{
    "model": "about.officer",
    "pk": 3,
    "fields": {
        "position": "Treasurer",
        "term_position_number": 2,
        "name": "Person 3",
        "start_date": "1984-01-01T00:00:00",
        "sfuid": "sfuid",
        "sfu_email_alias": "sfu_email_alias",
        "phone_number": 0,
        "github_username": "github_username",
        "gmail": "gmail",
        "course1": "",
        "course2": "",
        "language1": "",
        "language2": "",
        "bio": "",
        "image": "about_static/exec-photos/stockPhoto.jpg",
        "elected_term": 19841,
        "sfu_officer_mailing_list_email": "NONE"
    }
},
{
    "model": "about.officer",
    "pk": 4,
    "fields": {
        "position": "Secretary",
        "term_position_number": 3,
        "name": "Person 4",
        "start_date": "1984-01-01T00:00:00",
        "sfuid": "sfuid",
        "sfu_email_alias": "sfu_email_alias",
        "phone_number": 0,
        "github_username": "github_username",
        "gmail": "gmail",
        "course1": "",
        "course2": "",
        "language1": "",
        "language2": "",
        "bio": "",
        "image": "about_static/exec-photos/stockPhoto.jpg",
        "elected_term": 19841,
        "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", "sfu_email_alias", "github_username", "gmail") as $k (.;
         update( ["fields", $k]; $k )
       | update( ["fields", "phone_number"]; 0) ))