แยกหนึ่งฟิลด์จากอาร์เรย์ JSON เป็นอาร์เรย์ทุบตี


14

ฉันมีเอาต์พุต JSON ที่มีรายการของวัตถุที่เก็บอยู่ในตัวแปร (ฉันอาจไม่ได้ใช้ถ้อยคำที่ถูกต้อง)

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

ฉันต้องการค่าทั้งหมดสำหรับ item2 ในอาร์เรย์เพื่อให้สคริปต์ bash ทำงานบน ubuntu 14.04.1

ฉันได้พบวิธีมากมายในการรับผลลัพธ์ทั้งหมดลงในอาร์เรย์ แต่ไม่ใช่รายการที่ฉันต้องการ

คำตอบ:


18

ใช้ :

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

รหัส:

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

เอาท์พุท:

value2
value2_2

เป็นไปได้ไหมที่จะทำสิ่งนี้จากตัวแปรแทนที่จะเป็นไฟล์? ฉันพยายามหลีกเลี่ยงการเข้าถึงระบบไฟล์ส่วนเกินหากฉันไม่ต้องการ เมื่อฉันดึงอาเรย์นี้ฉันก็ใช้ json output
JpaytonWPD

1
คุณเคยลองอะไรบ้างไหม?
Gilles Quenot

2
jq . <<< "$json"มันเกี่ยวข้องกับเชลล์ (ทุบตี) ไม่เฉพาะเจาะจงกับjq
Gilles Quenot

1
วงเล็บที่ขาดหายไป:arr=( $(...) )
Gilles Quenot

4
jqคำสั่งที่ยอดเยี่ยมแต่โปรดอย่าแยกคำสั่งเอาต์พุตลงในอาร์เรย์ด้วยarr=( $(...) )(แม้ว่ามันจะทำงานกับตัวอย่างอินพุต): มันไม่ทำงานตามที่ต้องการด้วยช่องว่างที่ฝังตัวหรือนำ / ต่อท้ายและอาจส่งผลให้เกิดอุบัติเหตุโดยบังเอิญ
mklement0

5

ต่อไปนี้เป็นรถบั๊กกี้:

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

ให้ใช้:

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

... หรือดีกว่า ...

# 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

ขอบคุณ sputnick ฉันได้รับสิ่งนี้:

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

JSON ที่ฉันมีคือผลลัพธ์จาก API สิ่งที่ฉันต้องทำคือลบอาร์กิวเมนต์ไฟล์และไพพ์|เอาต์พุตของ curl ถึง jq ใช้งานได้ดีและบันทึกบางขั้นตอน


รหัสนั้นเป็นรถบั๊กจริงๆ ดูสิ่งที่เกิดขึ้นหากคุณมีองค์ประกอบผลลัพธ์*- มันจะถูกแทนที่ด้วยรายการไฟล์ในไดเรกทอรีปัจจุบันของคุณ
Charles Duffy

1
ในทำนองเดียวกันitem2ค่าที่มีช่องว่างในนั้นจะกลายเป็นมากกว่าหนึ่งองค์ประกอบอาร์เรย์
Charles Duffy

0

เป็นทางเลือกที่ง่ายดูที่jtcเครื่องมือ (ที่https://github.com/ldn-softdev/jtc ) เพื่อให้ได้สิ่งเดียวกัน (ตามตัวอย่าง jq):

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

คำอธิบายเกี่ยวกับ-wตัวเลือก: วงเล็บเหลี่ยม<...>ระบุการค้นหา json ทั้งหมดคำต่อท้ายlแนะนำให้ค้นหาป้ายกำกับแทนที่จะเป็นค่า+0แนะนำให้ค้นหาสิ่งที่เกิดขึ้นทั้งหมด (ไม่ใช่แค่ตัวแรก)


ข้อผิดพลาดเช่นเดียวกับarr=( $(jq ...) )คำตอบทั้งหมดตราบเท่าที่เนื้อหาจะถูกแยกสตริงและขยาย glob เพื่อเติมอาร์เรย์ - ความหมายช่องว่าง (ไม่เพียง แต่ขึ้นบรรทัดใหม่) สร้างองค์ประกอบใหม่และองค์ประกอบที่มีลักษณะเหมือนนิพจน์กลมจะถูกแทนที่ด้วยไฟล์ที่ การแสดงออกที่ตรงกับ
ชาร์ลส์ดัฟฟี่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.