如何在Shell脚本中读取JSON文件

Bash并没有内置支持直接处理JSON数据。然而,有各种工具可以在Bash脚本中帮助解析和操作JSON文件。在本文中,我们将使用jq,这是一个强大的命令行工具,专门为在Bash中处理JSON数据而设计。

file

jq是一个轻量级且灵活的命令行工具,允许我们轻松地提取、过滤和转换JSON数据。它为在Bash脚本中处理JSON文件提供了一种简单而有效的方式。jq的表达式语法简化了JSON操作任务。它能够处理复杂的JSON结构并提取特定的数据元素,使其成为在Bash脚本中读取JSON文件的理想选择。

jq官网:https://jqlang.github.io/jq/

提取键和值

在我们开始读取数据之前,我们首先需要一个JSON文件。在第一个示例中,我们将使用名为“example.json”的以下JSON文件。

{
 "name": "Mark",
 "age": 25,
 "email": "mark@example.com",
 "address": {
 "city": "London",
 "country": "England"
 },
 "hobbies": ["running", "cooking", "writing"],
 "is_student": true
}

让我们首先看一下jq命令以及它是如何工作的。我们可以将JSON内容管道传输到jq命令,或者我们可以直接使用jq命令访问它。

    $ cat example.json | jq

这两个命令都会打印出我们的JSON文件的全部内容。
现在让我们看一下如何提取某些值。比如说我们想获得“name”键的值。在这种情况下,我们可以运行以下命令。

    $ jq '.name' example.json“Mark”

我们可以基本理解这个命令是如何工作的。我们使用jq关键字调用命令,然后我们指定在引号中的键,前面加一个点。在第一个例子中,我们想读取所有的内容,所以我们只是在引号中放了一个点,没有指定要读取哪个键。
如果我们想要输出为原始字符串,我们可以使用-r标志,就像这样。

    $ jq -r '.name' example.json
Mark

现在,我们可以用所有这些来编写一个简单的bash脚本。

#!/bin/bash
input_file="example.json"
data_age=jq -r '.age' "$input_file"  
echo $data_age

input_file变量包含我们的JSON文件的名字,对于data_age变量,我们在反引号内指定了我们的命令。在bash中,反引号()用作命令替换,意味着它们内部的任何内容都将被视为应该运行的命令,并将被替换为命令的输出。最后,我们使用echo打印出我们的变量。

    $ chmod +x script.sh
    $ ./script.sh
    25

接下来,让我们看一下如何同时获取键和它的值。在这个例子中,我们将获取每个键及其值,然后将它们存储在它们的变量中。这是一个可以做到这一点的bash脚本。

#!/bin/bash
input_file="example.json"
mapfile -t json_data < <(jq -r "to_entries[] | \"\(.key)=\(.value|tostring)\"" "$input_file")
for pair in "${json_data[@]}"; do
 IFS='=' read -r key value <<< "$pair"
 echo "$key: $value"
done

从json文件中提取键和值的bash脚本

mapfile命令读取jq产生的输出的每一行,并将其存储在json_data数组中。我们是通过在<()括号内运行jq命令,并使用另一个<字符将其管道传输到mapfile命令来实现的。进程替换与我们在前一个脚本中使用的命令替换类似。
to_entries函数将JSON对象转换为键值对数组。[]运算符用于遍历该数组中的每个元素。然后我们指定我们想要将它们存储为键=值对,确保将最后的值转换为字符串。
然后,for循环遍历数组,从每对中提取键和值,并在分隔它们的单独行上打印它们。本质上,脚本从JSON文件中提取并显示键值对,提供了数据的人类可读表示。

遍历JSON数据

虽然我们在前一个脚本中使用了循环,但在这里我们有一个不同的应用。我们不是使用循环来获取每个键值对,而是使用它们来遍历我们新的JSON文件的父对象(员工)内的对象。

{
 "employees": [
 {
 "name": "John Doe",
 "age": 30,
 "email": "john.doe@example.com"
 },
 {
 "name": "Jane Smith",
 "age": 25,
 "email": "jane.smith@example.com"
 }
 ]
}
#!/bin/bash
input_file="example.json"
jq -r '.employees[] | "\(.name), \(.email)"' "$input_file" |
while IFS= read -r employee_info; do
 echo "Employee Info: $employee_info"
done

bash遍历JSON文件中的数组

我们使用循环来遍历JSON文件中的"employees"数组。通过使用jq和循环,我们可以提取和处理每个员工的"name"和"email"字段。jq表达式’.employees[] | "(.name), (.email)"’遍历"employees"数组,并将输出格式化为"name, email"。然后循环读取每一行,代表一个员工,并使用echo打印他们的信息。
在下面的例子中,我们将看到如何通过使用员工的年龄对每个元素执行操作。

#!/bin/bash
input_file="example.json"
jq -r '.employees[] | "\(.name), \(.email), \(.age)"' "$input_file" |
while IFS= read -r employee_info; do
 name=$(echo "$employee_info" | cut -d ',' -f1)
 email=$(echo "$employee_info" | cut -d ',' -f2)
 age=$(echo "$employee_info" | cut -d ',' -f3)
 age_in_days=$((age * 365))
 echo "Employee Name: $name"
 echo "Employee Email: $email"
 echo "Employee Age: $age years ($age_in_days days)"
 echo "--------------------------------"
done

file

我们扩展了前一个脚本,包括每个员工的"age"字段。在使用jq提取"name"、"email"和"age"之后,我们通过将年龄乘以365来计算员工的年龄(以天为单位)。循环打印员工的姓名、电子邮件和年龄(以年和天为单位),提供了每个员工信息的更详细视图。

使用JSON数据的条件处理

最后,我们将看一下如何使用提取的JSON数据进行条件语句。在下面的例子中,我们根据他们工作的部门对每个员工进行分类,并打印出这些数据。如果一个员工既不在三个指定的部门(工程、人力资源、销售)工作,我们就简单地打印出他们在一个未知的部门工作。再次我们修改了我们的JSON文件以适应这个例子。

{
 "employees": [
 {
 "name": "John Doe",
 "age": 30,
 "department": "Engineering"
 },
 {
 "name": "Jane Smith",
 "age": 25,
 "department": "HR"
 },
 {
 "name": "Michael Johnson",
 "age": 35,
 "department": "Sales"
 }
 ]
}
#!/bin/bash
input_file="example.json"
jq -r '.employees[] | "\(.name),\(.department)"' "$input_file" |
while IFS= read -r employee_info; do
 name=$(echo "$employee_info" | cut -d ',' -f1)
 department=$(echo "$employee_info" | cut -d ',' -f2)
 department=$(echo "$department" | awk '{$1=$1};1')
 case "$department" in
 Engineering)
 echo "$name works in the Engineering department."
 ;;
 HR)
 echo "$name works in the Human Resources department."
 ;;
 Sales)
 echo "$name works in the Sales department."
 ;;
 *)
 echo "$name works in an unknown department."
 ;;
 esac
done

使用jq进行条件处理的脚本输出

在这个脚本中,我们使用jq和循环进行条件处理,根据他们的"department"对员工进行分类。jq表达式’.employees[] | "(.name),(.department)"’提取每个员工的"name"和"department"字段。循环处理每个员工的数据,去除部门前面的空格,并使用case语句根据他们的部门打印自定义消息。这使我们能够根据JSON数据轻松地将员工分类到不同的部门。

Linux中黑洞/dev/null详解
Shell脚本如何与Expect交互?

发表我的评论

电子邮件地址不会被公开。 必填项已用*标注

31 + 16 =

ajax-loader