如何在 jq 中选择多个字段?

255

我的输入文件是以换行符分隔的 JSON (ndjson),看起来像这样:

{
  "login": "dmaxfield",
  "id": 7449977,
  ...
}
{
  "login": "dmaxfield",
  "id": 7449977,
  ...
}

我可以使用以下命令获取所有的login名称:cat members | jq '.[].login',但我还没有找到获取loginid的语法?

2
你能提供一个期望输出的例子吗?登录/ID对可以有很多种表示方式。 - user3899165
5个回答

337

你可以使用 jq '.[] | .login, .id' 来获取每个登录名及其ID。


3
用户的样例输入看起来像是一个对象流,但由于他们提供的样例脚本,我假设它被包装在一个数组中,只是他们省略了它。 - user3899165
1
@SantiagoLapresta:没有必要做出那种假设。jq与对象序列非常兼容 - 不需要数组包装器。需要删除...字符串和最后的逗号,但我认为这是暗示的。 - Peter V. Mørch
128
或者如果您只想显示这两个字段。jq '.[] | {login, id}' - Cameron Taggart
6
@CameronTaggart,如果我想显示“login.name”,应该怎么做? jq '.[] | {login.name, id}' 看起来似乎无效,正确的方式是什么,请告诉我? - zyxue
20
这是可行的:jq '.[] | {name: .login.name, id}'。它的意思是选取JSON对象中的每个元素(使用.[]),并从中提取login.name属性,将其命名为name,同时保留id属性,最终将这两个属性组成一个新的对象。 - Alex Grounds
显示剩余3条评论

153

这对我起作用:

> echo '{"a":1,"b":2,"c":3}{"a":1,"b":2,"c":3}' | jq '{a,b}'
{
  "a": 1,
  "b": 2
}
{
  "a": 1,
  "b": 2
}

1
这很简单,正好做到了我想要的:有多个输入对象/哈希,并仅取其中一些值,同时将它们作为对象输出。 - Smar
2
现在我可以在我的数字照片上使用这个命令:ls *jpg | xargs -n 1 exiftool -json | jq '{ SourceFile,CreateDate,CreationDate,Make,Model,DateTimeOriginal,SceneType,FileAccessDate,FileModifyDate,FileInodeChangeDate,SceneCaptureType,ModifyDate }' - Sridhar Sarnobat
7
注意不要在属性前加上 .,我花了一段时间才意识到这一点。 - Sridhar Sarnobat
正是我所需要的!不知道是否有办法使其适用于嵌套对象。 - chutz

51

这里再提供一个例子(jq-1.6):

遍历数组并选择对象元素的一个字段以及该对象中的另一个字段

echo '[{"id":1, "private_info": {"name": "Ivy", "age": 18}}, {"id":2, "private_info": {"name": "Tommy", "aga": 18}}]' | jq ".[] | {id: .id, name: .private_info.name}" -

{
  "id": 1,
  "name": "Ivy"
}
{
  "id": 2,
  "name": "Tommy"
}

没有示例数据:

jq ".[] | {id, name: .private_info.name}" -

.[]: 遍历数组

{id, name: .private_info.name}: 取出 .id 和 .private_info.name 并将其包装成一个对象,分别赋值给名为 "id" 和 "name" 的字段


1
将结构/键名包装成对象非常好,正是我正在寻找的。 - cryanbhu

27
为了选择缩进到不同层级的值(例如,第一层和第二层),您可以使用以下内容:
echo '[{"a":{"aa":1,"ab":2},"b":3,"c":4},{"a":{"aa":5,"ab":6},"b":7,"c":8}]' \
     | jq '.[]|[.a.aa,.a.ab,.b]'

[
  1,
  2,
  3
]
[
  5,
  6,
  7
]

8

对于 jq >= v1.7

内置函数 pick 对于切片对象(即投影)非常有用。

$ cat example.ndjson | jq -c 'pick(.login, .id)'
{"login":"dmaxfield","id":7449977}
{"login":"eiffel","id":7449978}

嵌套对象也可以很好地处理。
$ cat example.ndjson | jq -c 'pick(.login, .id, .nested.obj)'
{"login":"dmaxfield","id":7449977,"nested":{"obj":1.23}}
{"login":"eiffel","id":7449978,"nested":{"obj":4.56}}

如果您的输入格式为JSON而不是NDJSON,请在脚本前加上.[]
$ cat example.json | jq '.[] | pick(.login, .id)' | jq -s '.'   
[
  {
    "login": "dmaxfield",
    "id": 7449977
  },
  {
    "login": "eiffel",
    "id": 7449978
  }
]

对于 jq < v1.7

使用 { login, id },这是 { login: .login, id: .id } 的简写。

$ cat example.ndjson | jq -c '{ login, id }'                
{"login":"dmaxfield","id":7449977}
{"login":"eiffel","id":7449978}

对于嵌套对象,请按照以下方式编写:
$ cat example.ndjson | jq -c '{ login, id, nested: { obj: .nested.obj } }'
{"login":"dmaxfield","id":7449977,"nested":{"obj":1.23}}
{"login":"eiffel","id":7449978,"nested":{"obj":4.56}}

对于普通的JSON文件:
$ cat example.json | jq '.[] | { login, id }' | jq -s '.'
[
  {
    "login": "dmaxfield",
    "id": 7449977
  },
  {
    "login": "eiffel",
    "id": 7449978
  }
]

注意事项

我使用了以下的NDJSON文件和JSON文件。

$ cat example.ndjson 
{ "login": "dmaxfield", "id": 7449977, "foo": true, "nested": { "obj": 1.23 } }
{ "login": "eiffel", "id": 7449978, "foo": false, "nested": { "obj": 4.56 } }
$ cat example.json 
[
  { "login": "dmaxfield", "id": 7449977, "foo": true, "nested": { "obj": 1.23 } },
  { "login": "eiffel", "id": 7449978, "foo": false, "nested": { "obj": 4.56 } }
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接