Cách sử dụng lệnh jq để xử lý JSON trong Linux

Jq là một chương trình phân tích cú pháp mạnh mẽ và có tính linh hoạt cao, có thể truyền và lọc dữ liệu JSON ra khỏi các file và đường dẫn UNIX. Bài viết này sẽ hướng dẫn bạn những kiến thức cơ bản về jq, trình bày các ví dụ cũng như một số cách triển khai thay thế mà bạn có thể áp dụng ngay hôm nay.

jq được sử dụng để làm gì?

Cách sử dụng phổ biến nhất của jq là để xử lý và thao tác các phản hồi JSON từ API Software-as-a-Service (SaaS). Ví dụ, bạn có thể sử dụng jq cùng với cURL để khai thác các điểm cuối API của Digitalocean nhằm lấy thông tin chi tiết về tài khoản.

Quyền truy cập API mẫu cho Digitalocean tới jq.
Quyền truy cập API mẫu cho Digitalocean tới jq.

Ngoài ra, jq còn là một tiện ích mạnh mẽ để quản lý các file JSON lớn. Một số chương trình cơ sở dữ liệu phổ biến nhất hiện nay như MongoDB, PostgreSQL và MySQL hỗ trợ JSON như một cách để lưu trữ dữ liệu. Như vậy, việc học jq mang lại lợi thế trong việc hiểu cách các hệ thống cơ sở dữ liệu đó hoạt động.

Cài đặt và sử dụng jq

Để bắt đầu với jq, hãy cài đặt gói nhị phân của nó vào hệ thống:

sudo apt install jq

Tìm điểm cuối API mở mà bạn có thể kiểm tra jq. Trường hợp ví dụ sẽ sử dụng API kiểm tra IP của ipinfo.io.

Sử dụng trang web Jq Json Linux 02 Ipinfo Saas
Sử dụng trang web Jq Json Linux 02 Ipinfo Saas

Bộ lọc cơ bản nhất cho jq là bộ lọc dấu chấm (.). Lệnh sau sẽ xuất phản hồi JSON khi jq nhận được nó từ đầu vào tiêu chuẩn:

curl https://ipinfo.io/ | jq '.'

Một bộ lọc cơ bản khác là ký hiệu (|). Đây là một bộ lọc đặc biệt chuyển đầu ra của một bộ lọc làm đầu vào của bộ lọc khác:

curl https://ipinfo.io/ | jq '. | .ip'

Giá trị sau toán tử | là “Object Identifier-Index”. Thao tác này sẽ tìm kiếm đầu vào JSON để phát hiện bất kỳ biến nào khớp với văn bản của nó và in giá trị của nó trên terminal. Trường hợp ví dụ sau đang tìm giá trị của key “ip:”.

Đầu ra được lọc của API ipinfo SaaS thông qua jq.
Đầu ra được lọc của API ipinfo SaaS thông qua jq.

Với những điều cơ bản đã được thực hiện, các phần sau sẽ chỉ cho bạn một số thủ thuật có thể thực hiện khi sử dụng jq.

1. Tạo trình đọc nguồn cấp dữ liệu cơ bản với jq

Hầu hết các trang web hiện đại ngày nay đều cung cấp điểm cuối API mở để đọc dữ liệu bên trong nền tảng của họ. Ví dụ, mọi kho lưu trữ Github đều có URL API riêng để truy xuất các cam kết và vấn đề mới nhất cho dự án đó.

"Bức tường code" mặc định cho API Github.
"Bức tường code" mặc định cho API Github.

Bạn có thể sử dụng điểm cuối API như thế này với jq để tạo nguồn cấp dữ liệu “giống RSS” đơn giản của riêng mình. Để bắt đầu, hãy sử dụng cURL để kiểm tra xem điểm cuối có hoạt động tốt không:

curl https://api.github.com/repos/bitcoin/bitcoin/issues

Chạy lệnh sau để in mục nhập đầu tiên trong nguồn cấp dữ liệu:

curl https://api.github.com/repos/bitcoin/bitcoin/issues | jq '.[0]'

Điều này sẽ hiển thị các trường khác nhau mà API Github gửi tới jq. Bạn có thể sử dụng những thứ này để tạo đối tượng JSON tùy chỉnh của riêng mình bằng cách chuyển đầu vào tới bộ lọc dấu ngoặc nhọn ({}):

curl https://api.github.com/repos/bitcoin/bitcoin/issues | jq '.[0] | { title: .title }'

Việc thêm bộ lọc dấu phẩy (,) bên trong dấu ngoặc nhọn cho phép thêm nhiều trường vào đối tượng tùy chỉnh:

curl https://api.github.com/repos/bitcoin/bitcoin/issues | jq '.[0] | {title: .title, url: .html_url, author: .user.login}'
Một đối tượng JSON được loại bỏ tùy chỉnh từ API Github.
Một đối tượng JSON được loại bỏ tùy chỉnh từ API Github.

Việc xóa “0” bên trong dấu ngoặc vuông sẽ áp dụng bộ lọc jq cho toàn bộ nguồn cấp dữ liệu:

curl https://api.github.com/repos/bitcoin/bitcoin/issues | jq '.[] | {title: .title, url: .html_url, author: .user.login}'

Bạn cũng có thể tạo một script Bash nhỏ để hiển thị các vấn đề mới nhất từ dự án Github yêu thích của mình. Dán block code sau vào trong file script shell trống:

#!/bin/bash<br><br># usage: ./script.sh [0 ... 29]<br><br>REPO="https://api.github.com/repos/bitcoin/bitcoin/issues"<br><br>curl $REPO | jq ".[$1] | {title: .title, url: .html_url, author: .user.login}"

Lưu file, sau đó chạy lệnh sau để làm cho nó có thể thực thi được:

chmod u+x ./script.sh

Kiểm tra trình đọc nguồn cấp dữ liệu mới bằng cách liệt kê vấn đề mới nhất trong kho lưu trữ Github yêu thích:

./script.sh 0
Script tùy chỉnh đang hoạt động và xuất vấn đề Github gần đây nhất.
Script tùy chỉnh đang hoạt động và xuất vấn đề Github gần đây nhất.

2. Đọc và tìm kiếm thông qua cơ sở dữ liệu JSON

Ngoài việc đọc dữ liệu từ API, bạn cũng có thể sử dụng jq để quản lý các file JSON trong máy cục bộ của mình. Bắt đầu bằng cách tạo một file cơ sở dữ liệu JSON đơn giản bằng trình soạn thảo văn bản yêu thích:

nano ./database.json

Dán khối dữ liệu sau vào file, sau đó lưu nó:

[<br>    {"id": 1, "name": "Ramces", "balance": 20},<br>    {"id": 2, "name": "Alice", "balance": 30},<br>    {"id": 3, "name": "Bob", "balance": 10},<br>    {"id": 4, "name": "Charlie", "balance": 20},<br>    {"id": 5, "name": "Maria", "balance": 50}<br>]

Kiểm tra xem jq có đọc đúng file JSON hay không bằng cách in đối tượng đầu tiên trong mảng cơ sở dữ liệu:

jq '.[0]' database.json
jq đang in mục nhập đầu tiên trong cơ sở dữ liệu JSON.
jq đang in mục nhập đầu tiên trong cơ sở dữ liệu JSON.

Thực hiện truy vấn trên cơ sở dữ liệu JSON bằng bộ lọc “Object Identifier-Index”. Trong trường hợp này, tác giả bài viết đang tìm kiếm giá trị của key “.name” trên mọi mục nhập trong cơ sở dữ liệu:

jq '.[] | .name' database.json

Bạn cũng có thể sử dụng một số hàm tích hợp của jq để lọc các truy vấn dựa trên những đặc tính nhất định. Ví dụ, có thể tìm kiếm và in tất cả các đối tượng JSON có giá trị “.name” nhiều hơn 6 ký tự:

jq '.[] | select((.name|length)>6)' database.json
Đầu ra của jq với giới hạn độ dài tên.
Đầu ra của jq với giới hạn độ dài tên.

Hoạt động trên cơ sở dữ liệu JSON với jq

Ngoài ra, jq có thể hoạt động trên cơ sở dữ liệu JSON tương tự như bảng tính cơ bản. Ví dụ, lệnh sau in tổng của key “.balance” cho mọi đối tượng trong cơ sở dữ liệu:

jq '[.[] | .balance] | add' database.json

Bạn thậm chí có thể mở rộng điều này bằng cách thêm câu lệnh có điều kiện vào truy vấn của mình. Phần sau đây sẽ chỉ thêm “.balance” nếu giá trị “.name” của đối tượng thứ hai là “Alice”:

jq 'if .[1].name == "Alice" then [ .[] | .balance ] | add else "Second name is not Alice" end' database.json
Câu lệnh điều kiện trong jq đang chạy trên cơ sở dữ liệu.
Câu lệnh điều kiện trong jq đang chạy trên cơ sở dữ liệu.

Có thể tạm thời xóa các biến khỏi cơ sở dữ liệu JSON. Điều này có thể hữu ích nếu bạn đang kiểm tra bộ lọc và muốn đảm bảo rằng bộ lọc vẫn có thể xử lý tập dữ liệu:

jq 'del(.[1].name) | .[]' database.json
Mục nhập thứ hai không có key JSON name.
Mục nhập thứ hai không có key JSON name.

Bạn cũng có thể chèn các biến mới vào cơ sở dữ liệu bằng toán tử “+”. Ví dụ, dòng sau thêm biến “active: true” vào đối tượng đầu tiên trong cơ sở dữ liệu:

jq '.[0] + {active: true}' database.json
Một giá trị key bổ sung trên mục nhập cơ sở dữ liệu đầu tiên.
Một giá trị key bổ sung trên mục nhập cơ sở dữ liệu đầu tiên.

Lưu ý: Bạn có thể thực hiện các thay đổi vĩnh viễn bằng cách chuyển đầu ra của lệnh jq sang file cơ sở dữ liệu gốc:

jq '.[0] + {active: true}' database.json > database.json

3. Chuyển đổi dữ liệu không phải JSON trong jq

Một tính năng tuyệt vời khác của jq là nó có thể chấp nhận và hoạt động với dữ liệu không phải JSON. Để đạt được điều đó, chương trình sử dụng một “slurp mode thay thế, trong đó nó chuyển đổi bất kỳ dữ liệu được phân tách bằng dấu cách và dòng mới nào thành một mảng JSON.

Bạn có thể kích hoạt tính năng này bằng cách chuyển dữ liệu vào jq bằng flag -s:

echo '1 2' | jq -s .
Chuỗi văn bản được chuyển đổi thành một mảng JSON.
Chuỗi văn bản được chuyển đổi thành một mảng JSON.

Một lợi thế của việc chuyển đổi dữ liệu thô thành một mảng là bạn có thể xử lý chúng bằng cách sử dụng số chỉ mục mảng. Lệnh sau thêm hai giá trị bằng cách tham chiếu đến vị trí mảng được chuyển đổi của chúng:

echo '1 2' | jq -s '.[0] + .[1]'

Bạn có thể phát triển vị trí mảng này hơn nữa và xây dựng code JSON mới xung quanh nó. Chẳng hạn, code này chuyển đổi văn bản từ lệnh echo thành đối tượng JSON thông qua bộ lọc dấu ngoặc nhọn:

echo '6 "Mallory" 10' | jq -s '{"id": .[0], "name": .[1], "balance": .[2]}'
Đối tượng JSON tùy chỉnh ở định dạng của cơ sở dữ liệu mẫu.
Đối tượng JSON tùy chỉnh ở định dạng của cơ sở dữ liệu mẫu.

Ngoài việc lấy dữ liệu thô, jq còn có thể trả về dữ liệu không phải JSON làm đầu ra. Điều này hữu ích nếu bạn đang sử dụng jq như một phần của script shell lớn hơn và chỉ cần kết quả từ các bộ lọc của nó.

Để làm điều đó, hãy chạy jq theo sau là flag -r. Ví dụ, lệnh sau đọc tất cả tên từ file cơ sở dữ liệu và trả về dưới dạng dữ liệu plain text:

jq -r '.[] | .name' database.json
Danh sách các tên từ cơ sở dữ liệu đã bị loại bỏ định dạng.
Danh sách các tên từ cơ sở dữ liệu đã bị loại bỏ định dạng.
Thứ Hai, 22/04/2024 17:13
51 👨 148
0 Bình luận
Sắp xếp theo
    ❖ Linux