Menggunakan jq untuk mem-parsing dan menampilkan beberapa bidang dalam json secara serial

237

Saya punya Json ini

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

Menggunakan jq Saya ingin menampilkan nama depan dan belakang secara berurutan. Seperti begitu -

Stevie Wonder
Michael Jackson

Sejauh ini saya sudah sampai -

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

Tapi itu ditampilkan

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

Perhatikan yang berikut -

  1. Kutipan ganda yang tidak saya inginkan.
  2. Kembalinya kereta yang tidak saya inginkan.
  3. Ini kacau. Kueri saya menampilkan semua nama depan terlebih dahulu, lalu semua nama belakang. Namun, saya ingin pasangan pertama-terakhir, pertama-terakhir.
San
sumber

Jawaban:

339

Saya sarankan menggunakan Interpolasi String:

jq '.users[] | "\(.first) \(.last)"'

referensi

Eric Hartford
sumber
13
ini jauh lebih baik jika data Anda berupa angka
ozOli
203

Anda dapat menggunakan tambahan untuk string gabungan.

String ditambahkan dengan bergabung ke string yang lebih besar.

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

Di atas berfungsi ketika keduanya firstdan lastadalah string. Jika Anda mengekstraksi tipe data yang berbeda (angka dan string), maka kami perlu mengonversi ke tipe yang setara. Mengacu pada solusi pada pertanyaan ini . Sebagai contoh.

jq '.users[] | .first + " " + (.number|tostring)'
abraham
sumber
41
Untuk menghilangkan tanda kutip JSON, aktifkan jq dengan opsi -r, misalnya jq -r '.users [] | .pertama + "" +. terakhir '
puncak
4
+1, tetapi untuk kasus penggunaan saya, saya mencoba memformat dua angka pada baris yang sama. Pendekatan ini gagal karena tidak dapat menambah " "angka. Jawaban Eric memberikan hasil yang lebih baik untuk kasus ini.
Synesso
9
@Synesso: (.numA|tostring) + " " + (.numB|tostring)harus bekerja. Atau penggunaan interpolasi string sebagai gantinya: "\(.numA) \(.numB)".
LS
Ketika saya melakukannya jq '.users[] | .first + " " + .last', itu bekerja dengan sangat baik, tetapi menyebabkan garis baru antara nilai .firstdan .last. Saya mengubah " "ke "@"dan kemudian melakukan sed 's/@/ /g'pada output untuk mendapatkan "John Smith" sebagai output. Sesuatu seperti ini:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock
33
jq '.users[]|.first,.last' | paste - -
optman
sumber
14

Sementara kedua jawaban di atas berfungsi dengan baik jika kunci, nilainya adalah string, saya memiliki situasi untuk menambahkan string dan integer (kesalahan jq menggunakan ekspresi di atas)

Persyaratan: Untuk membuat url di bawah 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
}

Larutan:

curl http://192.168.99.103:8500/v1/catalog/service/apache-443 |
jq '.[0] | "http://" + .Address + ":" + "\(.ServicePort)"'
machzqcq
sumber
perhatikan bahwa lolos dari kurung tutup tidak diperlukan, dan akan salah.
Nymo
2
@nymo: Itu tidak keluar. \(...)adalah interpolasi string. Di sini ia mengubah angka .ServicePortmenjadi string. Interpolasi dapat digunakan sebagai pengganti +tanda - tanda untuk membuat solusi ini lebih pendek.
LS
12

Ini akan menghasilkan array nama

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

[
  "Stevie Wonder",
  "Michael Jackson"
]
TinyRoy
sumber
4

Saya cukup dekat dengan apa yang saya inginkan dengan melakukan sesuatu seperti ini

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

Keluaran yang cukup dekat dengan yaml bagi saya untuk biasanya mengimpornya ke alat lain tanpa banyak masalah. (Saya masih mencari cara untuk basicallt mengekspor subset dari input json)

ThorSummoner
sumber
1
Jenis pekerjaan ini dalam kasus saya, cukup drop | tr -d '"' di akhir, dan tambahkan opsi -r ke jq.
user842479
4

pendekatan saya akan (contoh json Anda tidak terbentuk dengan baik .. tebak itu hanya sampel)

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

mengembalikan sesuatu seperti ini

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

dan grep output dengan ekspresi reguler.

Ganesh Chandrasekaran
sumber