phân tích một trường từ một mảng JSON thành mảng bash


13

Tôi có một đầu ra JSON chứa danh sách các đối tượng được lưu trữ trong một biến. (Tôi có thể không nói đúng)

[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

Tôi cần tất cả các giá trị cho item2 trong một mảng để tập lệnh bash được chạy trên Ubuntu 14.04.1.

Tôi đã tìm thấy một loạt các cách để đưa toàn bộ kết quả vào một mảng nhưng không chỉ là các mục tôi cần

Câu trả lời:


17

Sử dụng :

$ cat json
[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

MÃ:

arr=( $(jq -r '.[].item2' json) )
printf '%s\n' "${arr[@]}"

ĐẦU RA:

value2
value2_2

Có thể làm điều này từ một biến thay vì một tập tin? Tôi cố gắng tránh truy cập hệ thống tập tin dư thừa nếu tôi không cần nó. Khi tôi kéo mảng này, tôi hoàn thành với đầu ra json.
JpaytonWPD

1
Bạn đã thử một cái gì đó?
Gilles Quenot

2
jq . <<< "$json"đó là vỏ (bash) liên quan, không cụ thểjq
Gilles Quenot

1
Thiếu dấu ngoặc đơn:arr=( $(...) )
Gilles Quenot

4
jqLệnh tuyệt vời , nhưng vui lòng không phân tích đầu ra lệnh thành một mảng với arr=( $(...) )(ngay cả khi nó hoạt động với đầu vào mẫu): nó không hoạt động như dự định với khoảng trắng được nhúng hoặc dẫn / theo dõi và có thể dẫn đến tình trạng toàn cầu hóa.
mkuity0

5

Sau đây là lỗi thực sự:

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

Thay vào đó, sử dụng:

# GOOD (with bash 4.x+), but can't detect failure
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

... hoặc, thậm chí tốt hơn ...

# GOOD (with bash 3.x+), *and* has nonzero status if curl or jq fails
IFS=$'\n' read -r -d '' -a arr \
  < <(set -o pipefail; curl --fail -k "$url" | jq -r '.[].item2' && printf '\0')

2

Nhờ sputnick tôi đã nhận được điều này:

arr=( $(curl -k https://localhost/api | jq -r '.[].item2') )

JSON tôi có là đầu ra từ một API. Tất cả những gì tôi cần làm là loại bỏ đối số tệp và |chuyển đầu ra của curl sang jq. Hoạt động tuyệt vời và lưu một số bước.


Mã đó thực sự là một lỗi nhỏ. Hãy xem điều gì xảy ra nếu bạn có một yếu tố kết quả *- nó sẽ được thay thế bằng một danh sách các tệp trong thư mục hiện tại của bạn.
Charles Duffy

1
Tương tự, một item2giá trị có khoảng trắng trong nó sẽ trở thành nhiều hơn một phần tử mảng.
Charles Duffy

0

như một cách thay thế dễ dàng, hãy xem jtccông cụ (tại https://github.com/ldn-softdev/jtc ), để đạt được điều tương tự (như trong ví dụ của jq):

bash $ arr=( $(jtc -w '<item2>l+0' file.json) )
bash $ printf '%s\n' "${arr[@]}"
"value2"
"value2_2"
bash $ 

giải thích về -wtùy chọn: dấu ngoặc nhọn <...>xác định tìm kiếm toàn bộ json, hậu tố lhướng dẫn tìm kiếm nhãn thay vì giá trị, +0hướng dẫn tìm tất cả các lần xuất hiện (thay vì chỉ lần đầu tiên).


Cùng một lỗi với tất cả các arr=( $(jq ...) )câu trả lời, trong trường hợp nội dung đang được phân tách chuỗi và mở rộng toàn cầu để điền vào mảng - có nghĩa là khoảng trắng (không chỉ dòng mới) tạo ra các phần tử mới và các phần tử trông giống như biểu thức toàn cầu được thay thế bằng các tệp biểu hiện phù hợp.
Charles Duffy
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.