Как вызвать jq внутри awk?

По существу у меня есть file.log, как следует

blah blah blah blah Hello world | {"foo": "bar"} blah blah Hello earth | {"foo1": "bar1"} 

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

  • Как заменить определенную строку с помощью sed или awk на основе команды run
  • Поиск указанных ключевых слов в файлах и копирование в новое имя файла на основе ключевого слова
  • Исключить скрытые подкаталоги из grep -r
  • Ошибка: неоднозначное перенаправление при передаче вывода команде
  • Добавить текст перед последним совпадающим поисковым словом в файле
  • Как объединить две команды grep и отобразить их результаты вместе?
  •  Hello earth | "bar" Hello earth | "bar1" 

    В настоящее время это то, что у меня есть:

     grep Hello file.log | awk -F "|" '{print $1, system("jq " $2)}' 

    Однако вызов jq дает мне эту ошибку:

     jq: error: syntax error, unexpected ':', expecting $end (Unix shell quoting issues?) at <top-level>, line 1: bin:application jq: 1 compile error 

    Я думаю, что из-за того, что внутри system () мои 12 $ лишены всех символов котировки ("), таким образом JQ не может распознать его json. Любое предложение?

  • Как умножить два столбца в awk?
  • Извлечение текста с помощью sed не работает должным образом
  • Поиск файлов для строки и если найден, проверьте, существует ли файл с парным именем в том же каталоге
  • строка grep, где следующая строка не содержит строки
  • Найти путь, который имеет конкретную подкаталоги
  • Печать только N-й строки перед каждой строкой, соответствующей шаблону
  • 2 Solutions collect form web for “Как вызвать jq внутри awk?”

    У вас здесь несколько проблем

    • system не возвращает что-то для печати, она возвращает значение выхода команды, которую вы выполнили (0, если все выполнено штрафом). Вы увидите ваши JSON-декодированные данные, а затем строку, такую ​​как Hello earth 0
    • двойные кавычки в вашей строке JSON проглатываются оболочкой. Результирующая команда, которую вы выполняете, – jq {foo: bar} (два аргумента, JSON больше не цитируется)
    • если $2 содержит специальные символы, такие как $ , ваша оболочка будет их интерпретировать
    • даже при правильном цитировании jq не называется подобным, он ожидает, что фильтр будет первым аргументом (например, « . »), и он ожидает, что вход JSON будет считан из файла или со стандартного ввода
    • построение команды из журналов и выполнение ее имеет огромные последствия для безопасности (что, если $2 было ; rm -rf ~ ?). Лучше избегайте этого, если сможете.

    Проблема безопасности, отложенная, представляет собой awk код, который будет работать большую часть времени:

     awk -F "|" '{ printf "%s", $1; system("echo \x27" $2 "\x27 | jq .")}' 

    То, что он делает, – отправить $2 в одиночные кавычки ( \x27 ) в jq через stdin.

    Проблемы остаются, хотя

    • если $2 содержит одиночную кавычку, она разбивает всю команду
    • если $2 начинается с тире (маловероятно), это будет интерпретироваться как опция для echo (мы можем использовать команду printf вместо echo )
    • проблема безопасности уже упоминалась (например, если $2 содержит ...'; rm -r ~; : ' ... любом месте строки)

    Теперь лучший код awk

     awk -F "|" '{ printf "%s", $1; print $2 | "jq ."; close("jq ."); }' 

    Поскольку $2 отправляется в jq процесс через stdin, но теперь, используя awk канал, он больше не интерпретируется оболочкой, решая все вышеперечисленные проблемы. Команда jq должна быть закрыта (завершена) в каждой строке, поэтому вызов close() .

    xhienne дал хороший обзор проблем с существующим кодом и хорошей альтернативой тому, что вы хотите достичь.

    Ниже приведена другая альтернатива: не пытайтесь вызвать jq из awk вообще, но пусть awk скрипт создает правильный вывод JSON.

     $ awk -F '|' 'BEGIN { print "[" } $2 { if (t) print t ","; t = $2 } END { print t, "]" }' file |jq . [ { "foo": "bar" }, { "foo1": "bar1" } ] 

    Код awk сам по себе будет генерировать следующий массив JSON из найденных объектов JSON (с учетом примера в вопросе):

     [ {"foo": "bar"}, {"foo1": "bar1"} ] 

    Это позволяет вам работать более свободно с jq не делая ваш скрипт слишком сложным для поддержания и понимания.

    Жонглирование переменной t в скрипте – это просто способ убедиться, что мы не получаем конечную запятую после последнего объекта JSON.

    Linux и Unix - лучшая ОС в мире.