Sử dụng jq để phân tích cú pháp và hiển thị nhiều trường trong một json ser chu


237

Tôi có Json này

{
    "users": [
        {
            "first": "Stevie",
            "last": "Wonder"
        },
        {
            "first": "Michael",
            "last": "Jackson"
        }
    ]
}

Sử dụng jq Tôi muốn hiển thị tên và họ một cách thanh thản. Thích như vậy -

Stevie Wonder
Michael Jackson

Đây là cách tôi đã nhận được -

jq '.users[].first, .users[].last'

Nhưng nó hiển thị

"Stevie"
"Michael"
"Wonder"
"Jackson"

Lưu ý những điều sau -

  1. Các trích dẫn kép mà tôi không muốn.
  2. Xe trở về mà tôi không muốn.
  3. Nó lộn xộn lên. Truy vấn của tôi hiển thị tất cả các tên đầu tiên, và sau đó tất cả các tên cuối cùng. Tuy nhiên, tôi muốn cặp đầu tiên, cuối cùng đầu tiên.

Câu trả lời:



203

Bạn có thể sử dụng bổ sung để nối chuỗi.

Chuỗi được thêm bằng cách nối vào một chuỗi lớn hơn.

jq '.users[] | .first + " " + .last'

Các công việc trên khi cả hai firstlastlà chuỗi. Nếu bạn đang trích xuất các kiểu dữ liệu khác nhau (số và chuỗi), thì chúng ta cần chuyển đổi thành các loại tương đương. Đề cập đến giải pháp cho câu hỏi này . Ví dụ.

jq '.users[] | .first + " " + (.number|tostring)'

41
Để loại bỏ các dấu ngoặc kép JSON, hãy gọi jq bằng tùy chọn -r, ví dụ jq -r '.users [] | .first + "" + .last '
cao điểm

4
+1, nhưng đối với trường hợp sử dụng của tôi, tôi đang cố định dạng hai số trên cùng một hàng. Cách tiếp cận này thất bại vì nó không thể thêm " "vào một số. Câu trả lời của Eric cho kết quả tốt hơn cho trường hợp này.
Synesso

9
@Synesso: (.numA|tostring) + " " + (.numB|tostring)nên làm việc. Hoặc sử dụng phép nội suy chuỗi thay thế : "\(.numA) \(.numB)".
LS

Khi tôi làm jq '.users[] | .first + " " + .last', nó hoạt động rất tốt, nhưng gây ra một dòng mới giữa giá trị của .first.last. Tôi đã thay đổi " "thành "@"và sau đó thực hiện một sed 's/@/ /g'đầu ra để lấy "John Smith" làm đầu ra. Một cái gì đó như thế này:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock


14

Mặc dù cả hai câu trả lời trên đều hoạt động tốt nếu khóa, giá trị là chuỗi, tôi đã gặp tình huống nối thêm chuỗi và số nguyên (lỗi jq sử dụng các biểu thức trên)

Yêu cầu: Để tạo một url ngoài json

pradeep@seleniumframework>curl http://192.168.99.103:8500/v1/catalog/service/apache-443 | jq .[0]
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   251  100   251    0     0   155k      0 --:--:-- --:--:-- --:--:--  245k
{
  "Node": "myconsul",
  "Address": "192.168.99.103",
  "ServiceID": "4ce41e90ede4:compassionate_wozniak:443",
  "ServiceName": "apache-443",
  "ServiceTags": [],
  "ServiceAddress": "",
  "ServicePort": 1443,
  "ServiceEnableTagOverride": false,
  "CreateIndex": 45,
  "ModifyIndex": 45
}

Giải pháp:

curl http://192.168.99.103:8500/v1/catalog/service/apache-443 |
jq '.[0] | "http://" + .Address + ":" + "\(.ServicePort)"'

lưu ý rằng việc thoát dấu ngoặc đơn là không cần thiết và sẽ sai.
nymo

2
@nymo: Đó không phải là thoát. \(...)là nội suy chuỗi. Ở đây nó biến số .ServicePortthành chuỗi. Nội suy có thể được sử dụng thay cho các +dấu hiệu để làm cho giải pháp này ngắn hơn.
LS

12

Điều này sẽ tạo ra một loạt các tên

> jq '[ .users[] | (.first + " " + .last) ]' ~/test.json

[
  "Stevie Wonder",
  "Michael Jackson"
]

4

Tôi đã khá gần với những gì tôi muốn bằng cách làm một cái gì đó như thế này

cat my.json | jq '.my.prefix[] | .primary_key + ":", (.sub.prefix[] | "    - " + .sub_key)' | tr -d '"' 

Đầu ra của nó đủ gần với yaml để tôi thường nhập nó vào các công cụ khác mà không gặp vấn đề gì nhiều. (Tôi vẫn đang tìm cách để cơ bản xuất một tập hợp con của json đầu vào)


1
Loại công việc này trong trường hợp của tôi, chỉ cần thả | tr -d '"' ở cuối và thêm tùy chọn -r vào jq.
user842479

4

Cách tiếp cận của tôi sẽ là (ví dụ json của bạn không được hình thành tốt .. đoán rằng đó chỉ là một mẫu)

jq '.Front[] | [.Name,.Out,.In,.Groups] | join("|")'  front.json  > output.txt

trả lại một cái gì đó như thế này

"new.domain.com-80|8.8.8.8|192.168.2.2:80|192.168.3.29:80 192.168.3.30:80"
"new.domain.com -443|8.8.8.8|192.168.2.2:443|192.168.3.29:443 192.168.3.30:443"

và grep đầu ra với biểu thức chính quy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.