[
{
"name": "user1",
"status": "off"
},
{
"name": "user2",
"status": "off"
},
{
"name": "user3",
"status": "on"
}
]
I want to know how I can search a JSON file recursively for the value of status
, for example, off
, and get all the name
values for which the status is off
.
Also, how can I change the value for user1
and user2
to on
?
I am using jq
and bash
.
Best Answer
To apply an expression to all elements of an array, and get an altered array out, use
map(expression)
.Extracting all entries that have
off
status:Mapping
select(.status == "off")
will alter the array by extracting (selecting) only the elements for which.status == "off"
is true.Extracting only the decoded names from the above:
Tucking on
[].name
at the end of the previous expression will first expand the array into a set of individual entries (that's what[]
does) and then extract the.name
value from each of those.You could also have used
... which creates an array of names from which you then extract all elements.
Setting the status to
on
for all entries that have anoff
status:By mapping
select(.status == "off").status = "on"
, we modify our array by setting the status toon
for any element whose status isoff
.Setting the status to
on
for entries based on explicit names:The same thing, but don't hard-code the names inside the expression. Rather, give them as a list at the end of the command line (note that
--args
and the list of names must be the last thing on the command line):The list of names given to
--args
is found in the array called$ARGS.positional
.The
IN(a; b)
thing returns true ifa
appears in the setb
. We're using$ARGS.positional[]
as the set to search, which is the set of the names given on the command line. This means ourselect()
here will extract only the elements whose names occur in the list on the command line, and these will have their status set toon
.Note that
IN(a; b)
differs from the similarly namedin(a)
, which returns true if a given value occurs as a key or index in the object or arraya
.Setting all entries' status to
on
:Follow-up question in comments:
The following uses an explicit
if
statement to change the status toon
for the given names and tooff
for all others:Or, in a one-line layout:
If I instead interpret the follow-up as not wanting to change the status of the given names, no matter what their statuses are, but to change all other statuses to
off
. In that case, we can negate the condition used in a previous variation:Note the added
| not
afterIN(...; ...)
.Of course, you could have used an
if
statement in most of the above variations too, but I like usingselect()
when I'm able to.