ใช้ jq เพื่อแยกวิเคราะห์และแสดงหลายเขตข้อมูลใน json ลำดับ


237

ฉันมี Json นี้

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

ใช้ jq ฉันต้องการแสดงชื่อและนามสกุลตามลำดับ ชอบมาก

Stevie Wonder
Michael Jackson

นี่เป็นวิธีที่ฉันได้รับ -

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

แต่มันจะแสดง

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

แจ้งให้ทราบดังต่อไปนี้ -

  1. คำพูดคู่ที่ฉันไม่ต้องการ
  2. การรับขนคืนที่ฉันไม่ต้องการ
  3. มันหงุดหงิด แบบสอบถามของฉันแสดงชื่อทั้งหมดก่อนจากนั้นจึงแสดงนามสกุลทั้งหมด อย่างไรก็ตามฉันต้องการคู่แรก - คู่สุดท้าย - คู่สุดท้าย

คำตอบ:



203

คุณสามารถใช้การเพิ่มเพื่อต่อสตริงเข้าด้วยกัน

สตริงถูกเพิ่มโดยการรวมเข้ากับสตริงที่มีขนาดใหญ่กว่า

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

การทำงานด้านบนเมื่อทั้งสองfirstและlastเป็นสตริง หากคุณกำลังแยกประเภทข้อมูลที่แตกต่างกัน (จำนวนและสตริง) เราจำเป็นต้องแปลงเป็นประเภทที่เทียบเท่า อ้างถึงวิธีแก้ปัญหาสำหรับคำถามนี้ ตัวอย่างเช่น.

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

41
หากต้องการกำจัดเครื่องหมายอัญประกาศ JSON ให้เรียกใช้ jq ด้วยตัวเลือก -r เช่น jq -r '.users [] | .first + "" + .last '
สูงสุด

4
+1 แต่สำหรับกรณีการใช้งานของฉันฉันพยายามจัดรูปแบบตัวเลขสองตัวในแถวเดียวกัน วิธีการนี้ล้มเหลวเนื่องจากไม่สามารถเพิ่ม" "ตัวเลขได้ คำตอบของ Eric ให้ผลลัพธ์ที่ดีกว่าสำหรับกรณีนี้
Synesso

9
@Synesso: (.numA|tostring) + " " + (.numB|tostring)ควรจะทำงาน "\(.numA) \(.numB)"หรือการใช้สตริงแก้ไขแทน:
LS

เมื่อฉันได้jq '.users[] | .first + " " + .last'ก็ทำงานดีมาก แต่ที่เกิดขึ้นบรรทัดใหม่ระหว่างมูลค่าของที่และ.first .lastผมเปลี่ยน" "ไป"@"แล้วได้sed 's/@/ /g'ในการส่งออกที่จะได้รับ "จอห์นสมิ ธ" เป็นเอาท์พุท บางสิ่งเช่นนี้:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock


14

ในขณะที่คำตอบข้างต้นทั้งสองทำงานได้ดีถ้าคีย์ค่าเป็นสตริงฉันมีสถานการณ์ที่จะผนวกสตริงและจำนวนเต็ม (ข้อผิดพลาด jq โดยใช้การแสดงออกข้างต้น)

ความต้องการ: เพื่อสร้าง URL ด้านล่าง 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
}

สารละลาย:

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

โปรดทราบว่าไม่จำเป็นต้องหลีกเลี่ยงวงเล็บปิดและจะเกิดข้อผิดพลาด
nymo

2
@ นีโม: มันไม่ได้หลบหนี \(...)คือการแก้ไขสตริง นี่มันเปลี่ยนตัวเลข.ServicePortเป็นสตริง การแก้ไขสามารถใช้แทน+สัญญาณเพื่อทำให้วิธีนี้สั้นลง
LS

12

สิ่งนี้จะสร้างอาร์เรย์ของชื่อ

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

[
  "Stevie Wonder",
  "Michael Jackson"
]

4

ฉันเข้าใกล้สิ่งที่ฉันต้องการด้วยการทำอะไรแบบนี้

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

ผลลัพธ์ที่ใกล้เคียงกับ yaml สำหรับฉันที่จะนำเข้าสู่เครื่องมืออื่น ๆ โดยไม่มีปัญหามาก (ฉันยังคงมองหาวิธีพื้นฐานในการส่งออกชุดย่อยของอินพุต json)


1
งานประเภทนี้ในกรณีของฉันเพียงแค่วาง | tr -d '"' ที่ส่วนท้ายและเพิ่มตัวเลือก -r ใน
jq

4

วิธีการของฉันจะเป็น (ตัวอย่าง json ของคุณไม่ได้เกิดขึ้นอย่างดี .. เดาว่าเป็นเพียงตัวอย่าง)

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

ส่งกลับบางสิ่งเช่นนี้

"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"

และ grep ผลลัพธ์ด้วยนิพจน์ทั่วไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.