Використання jq для розбору та відображення декількох полів у json послідовно


237

У мене є цей Джонсон

{
    "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, але для мого використання я намагаюся відформатувати два числа в одному рядку. Цей підхід не вдається, оскільки він не може додати " "число. Відповідь Еріка дає кращий результат у цьому випадку.
Синесо

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
@nymo: Це не втече. \(...)- це рядкова інтерполяція. Ось це число перетворюється .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 '"' наприкінці, а додати jr опцію jq.
user842479

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"

і промальовуйте вихід із регулярним виразом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.