使用 jq 进行 JSON 数据处理

LinuxLinuxBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

欢迎来到 Linux jq 编程实验!在这个实验中,你将探索如何使用 jq,一个轻量级且多功能的命令行 JSON 处理器。可以将 jq 看作是 sed,但它是专门为 JSON 数据设计的。它使你能够轻松地切片、过滤、映射和转换结构化数据。本实验旨在通过你可以应用于实际场景的实践示例,指导你从 jq 的基本用法到高级用法,例如处理来自 API 或配置文件的 JSON 数据。

想象一下,你正在计划一次去中国的旅行,并使用一个旅游应用程序,该应用程序提供有关各种景点的详细信息,包括它们的位置、开放时间和评论。该应用程序的后端以 JSON 格式存储这些数据。你的任务是提取特定的信息片段,以便有效地计划你的旅行。本实验将演示如何使用 jq 查询和操作这些 JSON 数据,使你能够快速识别最适合参观的景点。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("`Linux`")) -.-> linux/BasicFileOperationsGroup(["`Basic File Operations`"]) linux(("`Linux`")) -.-> linux/InputandOutputRedirectionGroup(["`Input and Output Redirection`"]) linux/BasicFileOperationsGroup -.-> linux/cat("`File Concatenating`") linux/InputandOutputRedirectionGroup -.-> linux/pipeline("`Data Piping`") subgraph Lab Skills linux/cat -.-> lab-279945{{"`使用 jq 进行 JSON 数据处理`"}} linux/pipeline -.-> lab-279945{{"`使用 jq 进行 JSON 数据处理`"}} end

基本 JSON 查询

让我们从学习如何从 JSON 对象中提取简单数据开始。

你现在应该在你的 /home/labex/project/ 目录下有 data.txt 文件。它包含表示景点列表的 JSON 数据。该文件内容如下所示:

[
  {
    "name": "The Great Wall of China",
    "location": "Shanxi Province",
    "opening_hours": "24 hours"
  },
  {
    "name": "Terracotta Warriors",
    "location": "XiAn",
    "opening_hours": "9:00 AM -  5:00 PM"
  }
]

我们这里的目标是提取此 JSON 数据中列出的所有景点的名称。

为了实现这个目标,使用以下命令:

cat ~/project/data.txt | jq '.[] | .name'

此命令将产生以下输出:

"The Great Wall of China"
"Terracotta Warriors"

让我们分解一下这个命令中发生了什么。cat ~/project/data.txt 只是读取 data.txt 文件的内容。| 符号,称为管道(pipe),将 cat 命令的输出作为输入传递给 jq 命令。提取逻辑的核心在于 jq '.[] | .name'。以下是 jq 如何处理它的:

  • .[] 告诉 jq 遍历 JSON 数组中的每个元素(在本例中,是每个景点对象)。
  • | 再次将迭代的结果传递给下一个操作,在本例中是 .name
  • .name 从每个景点对象中提取与 "name" 键关联的值。

本质上,该命令遍历每个景点,选出其名称并显示它。

过滤 JSON 数据

让我们继续学习如何根据特定条件过滤 JSON 数据。

我们的目标是只找到那些 24 小时开放的景点。

使用以下命令来完成此操作:

cat ~/project/data.txt | jq '.[] | select(.opening_hours == "24 hours") | .name'

执行此命令将输出:

"The Great Wall of China"

以下是过滤的工作原理:该命令以 cat ~/project/data.txt | jq '.[]' 开始,和之前一样,它读取文件并遍历每个景点。关键部分是添加了 select(.opening_hours == "24 hours")

  • select() 是一个 jq 函数,允许你根据你指定的条件过滤 JSON 的元素。
  • 条件 .opening_hours == "24 hours" 检查 opening_hours 字段的值是否完全等于字符串 "24 hours"。只有符合此条件的景点才会被传递到下一阶段。
  • 最后一部分 | .name 只是提取每个通过过滤器的景点的名称。

在本例中,只有“The Great Wall of China”满足条件,因此它是唯一被提取和显示的名称。

转换 JSON 数据

现在,让我们探索如何将 JSON 数据转换为不同的、更有用的格式。

我们这里的目标是使开放时间更具可读性。具体来说,如果一个景点 24 小时开放,我们希望显示“Open 24 hours”;否则,我们将在现有的开放时间文本前添加前缀“Open ”。

使用以下命令来实现此目的:

cat ~/project/data.txt | jq '.[] | {name: .name, location: .location, opening_hours: (.opening_hours | if . == "24 hours" then "Open 24 hours" else "Open \(.)" end)}'

此命令产生以下输出:

{
  "name": "The Great Wall of China",
  "location": "Shanxi Province",
  "opening_hours": "Open 24 hours"
}
{
  "name": "Terracotta Warriors",
  "location": "XiAn",
  "opening_hours": "Open 9:00 AM -  5:00 PM"
}

让我们理解一下这个转换:和之前一样,cat ~/project/data.txt | jq '.[]' 通过读取文件并遍历数组中的每个景点来开始。此转换的核心在于对象构造和 if-else 语句:

  • {name: .name, location: .location, opening_hours: ...} 创建一个新的 JSON 对象,从原始对象中提取数据。它直接包含原始对象的 namelocation。但是,opening_hours 字段的值更为复杂。
  • (.opening_hours | if . == "24 hours" then "Open 24 hours" else "Open \(.)" end) 获取原始 opening_hours 的值并对其进行处理:
    • .opening_hours 选择原始的开放时间值。
    • if . == "24 hours" then "Open 24 hours" else "Open \(.)" end 语句检查原始的 opening_hours 是否完全等于 "24 hours"。如果是,则将该值替换为 "Open 24 hours"。如果不是,则将 "Open " 作为前缀添加到现有的 opening_hours。请注意 \(.) 的使用,它允许我们将值嵌入到字符串中。

本质上,此命令通过为每个景点创建一个新对象并调整 opening_hours 值,使其对用户更具可读性,从而转换数据。

总结

恭喜你!你已成功完成 Linux jq 编程实验。你已经学会了如何使用 jq 查询、过滤和转换 JSON 数据,jq 是一个强大的工具,可以直接从命令行处理结构化数据。无论你是处理来自 API、配置文件还是任何其他 JSON 来源的数据,jq 都能让你高效且清晰地提取、过滤和操作所需的数据。

请记住,持续的练习对于掌握 jq 和其他命令行工具至关重要。请随意使用你自己的 JSON 数据进行实验,尝试不同的查询和转换。祝你编程愉快!

您可能感兴趣的其他 Linux 教程