#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
аргумента toread
,-j
аргумента tojq
и использование"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'
Примечания:
- Ваш пример ввода представляет собой множественный объект, а не массив объектов, поэтому
--slurp
используется. Если это не так, вам нужно будет удалить этот флаг. pubKey
в нем не может быть ‘>’, поэтому я использовал его в качестве разделителя. Это предполагает, что ваши данные поступают из надежного источника и не приведут к сбоям в вашей системе.
Комментарии:
1.
sh -c '...{}...'
создает серьезные риски для безопасности. Что, если ваш JSON имеет$(rm -rf ~)
внутри извлекаемой строки?2. @CharlesDuffy если pubKey не заслуживает доверия, то использование
>
в качестве разделителя невозможно в любом случае. Я начинаю с предположения, что данные безопасны.3. «Невозможно»? Возможно, вам придется беспокоиться о том, что элементы вводят дополнительные разделители, но это не повышает уровень приветствия атак с использованием инъекций.
4. Начинать с предположения о безопасности данных неразумно — количество разработчиков, которые делают сопоставимые предположения, является важной частью того, почему существует моя отрасль (анализ вредоносных программ). Следуйте безопасным методам, даже если вы думаете , что пишете что-то, что не подвергается атаке, и тогда вам не докажут, что вы ошибались, когда системы взаимодействуют неожиданным образом.
5. (Кстати, при обсуждении надежности мне нравится использовать определение NSA: «Доверенный» компонент — это тот, который может скомпрометировать вашу систему в случае сбоя в одиночку, без каких-либо других компонентов, отказывающих в тандеме. Размышляя в этих терминах, становится очевидным, почему доверять вещам — будь то значения данных, подсистемы или тому подобное — вредно)