Использование jq с bash для запуска команды для каждого объекта в массиве

Как я могу запустить команду bash для каждого json-объекта в массиве json с помощью jq? Пока у меня есть это:

cat credentials.json | jq -r '.[] | .user, .date, .email' | mycommand -u {user} -d {date} -e {email}

Это не работает. Как я могу взять параметры из массива json в мою команду?

Мой json файл выглядит примерно так:

[
   "user": "danielrvt",
   "date": "11/10/1988",
   "email": "[email protected]",
   ...
]

Ответ 1

Лучше всего, чтобы вывести каждую запись в формате TSV, а затем прочитать это из цикла оболочки.

jq -r '.[]|[.user, .date, .email] | @tsv' |
  while IFS=$'\t' read -r user date email; do
    mycommand -u "$user" -d "$date" -e "$email"
  done

jq сам по себе не имеет ничего похожего на вызов system для запуска внешней команды из фильтра, хотя кажется, что они работают на нем.

Ответ 2

Вы могли бы jq выводить команды для выполнения, что-то вроде

.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"

Затем выполните его. Что-то вроде

bash <(jq -r '.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"' foo)

Ответ 3

С xargs:

curl localhost:8082/connectors | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 

Или эквивалентно, чтобы показать вывод этого первого завитка:

echo '["quickstart-file-sink4","quickstart-file-source","quickstart-file-sink","quickstart-file-sink2","quickstart-file-sink3","quickstart-file-source2"]' | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 

jq .[] убирает один уровень содержания, так что список становится выводимым как одна строка на элемент.

xargs -L1 обрабатывает одну строку за раз

xargs -I'{}' указывает, что строка {} должна быть заменена строкой ввода при вызове следующей команды.

xargs по сути является оператором отображения для оболочки.

Ответ 4

Недавно я столкнулся с той же проблемой, когда xargs не очень помогает из-за относительно сложного набора аргументов, которые я хотел бы передать. Таким образом, я реализовал фильтр sh (и его друзей) для jq. У меня еще не было достаточно времени, чтобы написать документацию и тесты для нее, поэтому я не создавал PR, чтобы он стал частью официальной базы кода. Так что теперь это только для тех, кто готов самостоятельно скомпилировать эту версию:

https://github.com/haochenx/jq/tree/sh-support

Ответ 5

Вот еще один вариант, который я основал на ответе @chepner.

echo "$config" | jq -c '.[]' |
while IFS=$"\n" read -r c; do
    echo "start"
    host=$(echo "$c" | jq -r '.host')
    echo $host
    echo "end"
done

Я использовал опцию jq -c для вывода "компактных" jsons, чтобы они все были в одной строке.

В сочетании с IFS=$"\n" я смог зациклить каждый элемент во входном массиве json и делать то, что хотел.

Итак, с вводом

[
 {
  "host": "host1",
  "settings": {}
 },
 {
  "host": "host1",
  "settings": {}
 }
]

вывод

start
host1
end
start
host2
end