JSON dizisinden bir alanı bash dizisine ayrıştırma


14

Bir değişkende depolanan nesnelerin listesini içeren bir JSON çıktı var. (Bunu doğru ifade etmeyebilirim)

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

Ben ubuntu 14.04.1 üzerinde çalıştırmak için bir bash komut dosyası için bir dizi item2 için tüm değerlere ihtiyacım var.

Tüm sonucu bir diziye almanın bir yolunu buldum ama sadece ihtiyacım olan öğeleri değil

Yanıtlar:


18

kullanarak :

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

KODU:

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

ÇIKTI:

value2
value2_2

Bunu dosya yerine bir değişkenden yapmak mümkün müdür? İhtiyacım yoksa aşırı dosya sistemi erişiminden kaçınmaya çalışırım. Ben bu dizi çekmek kez json çıkışı ile yapılır.
JpaytonWPD

1
Bir şey denedin mi?
Gilles Quenot

2
jq . <<< "$json"kabuk (bash) ile ilgili, spesifik değiljq
Gilles Quenot

1
Eksik parantezler:arr=( $(...) )
Gilles Quenot

4
Harika bir jqkomut, ancak lütfen komut çıktısını bir diziye ayrıştırmayın arr=( $(...) )(örnek girişle çalışmasına rağmen): gömülü veya önde / sondaki boşluk ile amaçlandığı gibi çalışmaz ve yanlışlıkla globbing ile sonuçlanabilir.
mklement0

6

Aslında bu adamcağız:

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

Bunun yerine şunu kullanın:

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

... ya da daha iyisi ...

# 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 sayesinde bunu aldım:

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

Sahip olduğum JSON bir API çıktısıdır. Wans yapmak için gereken tek şey dosya argümanını kaldırmak ve |curl çıktısını jq için boru . Harika çalışıyor ve bazı adımlar kaydetti.


Bu kod aslında biraz hatalı. Sonuç *öğeniz varsa ne olduğuna bakın - geçerli dizininizdeki dosyaların bir listesiyle değiştirilir.
Charles Duffy

1
Benzer şekilde, item2içinde boşluk olan bir değer birden fazla dizi öğesi haline gelir.
Charles Duffy

0

kolay bir alternatif olarak, aynı şeyi elde etmek için jtcaraca bakın ( https://github.com/ldn-softdev/jtc adresinde ) (jq örneğinde olduğu gibi):

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

-wseçenek hakkında açıklama : köşeli parantez <...>tüm json arama belirtmek, sonek ldeğerleri yerine etiketleri aramak için +0talimatlar, tüm olayları (sadece bir tane yerine) bulmak için talimat verir.


Tüm arr=( $(jq ...) )cevaplarla aynı hata , içeriği diziyi doldurmak için dize-bölünmüş ve glob-genişlemiş olduğu sürece - yani boşluklar (sadece yeni satırlar değil) yeni öğeler oluşturur ve bir glob ifadesine benzeyen öğeler, ifade eşleşir.
Charles Duffy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.