介绍
欢迎来到 Linux jq 编程实验!在这个实验中,你将探索如何使用 jq,一个轻量级且多功能的命令行 JSON 处理器。可以将 jq 看作是 sed,但它是专门为 JSON 数据设计的。它使你能够轻松地切片、过滤、映射和转换结构化数据。本实验旨在通过你可以应用于实际场景的实践示例,指导你从 jq 的基本用法到高级用法,例如处理来自 API 或配置文件的 JSON 数据。
想象一下,你正在计划一次去中国的旅行,并使用一个旅游应用程序,该应用程序提供有关各种景点的详细信息,包括它们的位置、开放时间和评论。该应用程序的后端以 JSON 格式存储这些数据。你的任务是提取特定的信息片段,以便有效地计划你的旅行。本实验将演示如何使用 jq 查询和操作这些 JSON 数据,使你能够快速识别最适合参观的景点。
基础 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 对象,从原始对象中提取数据。它直接包含原始对象的name和location。但是,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 数据进行实验,尝试不同的查询和转换。祝你编程愉快!



