Как передать каждый вывод jq-фильтра во внешнюю команду?

#json #pipe #jq

#json #передача #jq

Вопрос:

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

Например, если у меня есть следующий JSON файл:

 {
  "id": 1,
  "corp": "Slate Rocks",
  "pubKey": "-----BEGIN PUBLIC KEY-----nMFowDQYJKoZIhvcNAQEBBQADSQAwRgJBAMBUAZGIzQsPO1PXgjdCJUxcZNc6Y4FYncVC JxZIUfaz0WkLI7H4tiKCsd 2F 3Xf hObSbdoUi1UuT5uzpsda8CAQM=n-----END PUBLIC KEY-----",
  "update": "2018-12-10"
}
{
  "id": 2,
  "corp": "Pi-ryte",
  "pubKey": "-----BEGIN PUBLIC KEY-----nMFowDQYJKoZIhvcNAQEBBQADSQAwRgJBALzXcOJvZz2UFPDJphTm  Ho9t lkTQfnxH0nSp7lbfCHL5Y5YbnD7pgbD/e/PGIHt cch3foOlUyH b0Ht53ZO0CAQM=n-----END PUBLIC KEY-----",
  "update": "2019-03-14"
}
{
  "id": 3,
  "corp": "Marble Dreams",
  "pubKey": "-----BEGIN PUBLIC KEY-----nMFowDQYJKoZIhvcNAQEBBQADSQAwRgJBAN1L9v8ZbpJ1/GMlNOfGFjQhhO2KTKpjnOfp97CDUdCAQ6wzLjagGKbySC16/MpnAvoPUmYEtTRtbdH/rdMGdvd8CAQM=n-----END PUBLIC KEY-----",
  "update": "2018-12-17"
}
  

и я хочу вывести модули открытого ключа RSA, мне нужно выполнить openssl для каждого "pubKey" значения.

Это работает только для первого "pubKey" :

 $ jq -r '.pubKey' seq.json | openssl rsa -pubin -noout -modulus
Modulus=C054019188CD0B0F3B53D7823742254C5C64D73A6381587150BE27164851F6B3D1690B23B1F8B62282B1DFB617EDD77FE84E6D26DDA148B552E4F9BB3A6C75AF
  

Есть ли что-то вроде:

 $ jq -r '.pubKey | system("openssl rsa -pubin -noout -modulus")' seq.json
  

или

 $ jq -r '.pubKey as $pk | system("openssl rsa -pubin -noout -modulus -in $pk")' seq.json
  

Ответ №1:

Реализация, которая старается не выполнять данные в виде кода, может выглядеть следующим образом:

 while IFS= read -r -d '' chunk; do
  openssl rsa -pubin -noout -modulus <<<"$chunk"
done < <(jq -j '(.pubKey, "u0000")' seq.json)
  
  • while read Идиома подробно описана в BashFAQ # 1
  • Использование подстановки процесса ( <(...) синтаксис) по причинам, описанным в BashFAQ #24.
  • Использование -d аргумента to read , -j аргумента to jq и использование "u0000" внутри JSON использует разделители NUL для разделения извлеченных элементов данных. Они используются, потому что NUL — это единственный символ, который не может быть представлен внутри строк C; таким образом, они могут использоваться для представления разделителей между любым элементом данных, который программа C может сохранить в строке. Смотрите stedolan / jq # 1271 историю этой функции в jq.

Комментарии:

1. Потрясающе! Это какой-то серьезный сбой-фу !

2. Для чего в jq фильтре круглые скобки?

3. Скобки здесь на самом деле не важны — важна запятая, генерирующая последовательность (терминология XQuery, а не терминология jq, но здесь они ведут себя концептуально идентично), так что jq сначала выдает содержимое, стоящее за .pubQuery , затем выдает буквальный NUL ; поскольку мы используем -j , между этими двумя (или любыми другими) элементами нет разделителя. Лично я считаю, что скобки облегчают чтение таких последовательностей, ограничивая их границы, но это предпочтение, а не необходимость.

Ответ №2:

Вместо того, чтобы делать это внутри jq, поскольку jq пока не может использовать program в качестве фильтра, вы можете сделать это вне его:

 jq -j --slurp 'map(.pubKey) | join(">")' seq.json | xargs --delimiter=> -n1 --no-run-if-empty -i sh -c 'echo "{}" | openssl rsa -pubin -noout -modulus'
  

Примечания:

  1. Ваш пример ввода представляет собой множественный объект, а не массив объектов, поэтому --slurp используется. Если это не так, вам нужно будет удалить этот флаг.
  2. pubKey в нем не может быть ‘>’, поэтому я использовал его в качестве разделителя. Это предполагает, что ваши данные поступают из надежного источника и не приведут к сбоям в вашей системе.

Комментарии:

1. sh -c '...{}...' создает серьезные риски для безопасности. Что, если ваш JSON имеет $(rm -rf ~) внутри извлекаемой строки?

2. @CharlesDuffy если pubKey не заслуживает доверия, то использование > в качестве разделителя невозможно в любом случае. Я начинаю с предположения, что данные безопасны.

3. «Невозможно»? Возможно, вам придется беспокоиться о том, что элементы вводят дополнительные разделители, но это не повышает уровень приветствия атак с использованием инъекций.

4. Начинать с предположения о безопасности данных неразумно — количество разработчиков, которые делают сопоставимые предположения, является важной частью того, почему существует моя отрасль (анализ вредоносных программ). Следуйте безопасным методам, даже если вы думаете , что пишете что-то, что не подвергается атаке, и тогда вам не докажут, что вы ошибались, когда системы взаимодействуют неожиданным образом.

5. (Кстати, при обсуждении надежности мне нравится использовать определение NSA: «Доверенный» компонент — это тот, который может скомпрометировать вашу систему в случае сбоя в одиночку, без каких-либо других компонентов, отказывающих в тандеме. Размышляя в этих терминах, становится очевидным, почему доверять вещам — будь то значения данных, подсистемы или тому подобное — вредно)