Как я могу отформатировать файл json в переменной среды bash?

Я пытаюсь взять содержимое файла конфигурации (формат JSON), удалить лишние новые строки и пробелы, чтобы быть кратким, а затем назначить его переменной среды перед запуском моего приложения.

Вот где я до сих пор:

pwr_config=`echo "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync(process.argv[2], 'utf-8'))));" | node - config.json | xargs -0 printf '%q\n'` npm run start

Это направляет короткое приложение node.js в среду выполнения узла, принимая в качестве аргумента имя файла, и оно анализирует и преобразует файл JSON в строку, чтобы проверить его и удалить все ненужные пробелы. Все идет нормально.

Результат этого затем передается в printf, или, по крайней мере, так оно и было бы, но printf, по-видимому, не поддерживает ввод таким образом, поэтому я использую xargs, чтобы передать его так, как он поддерживает.

Я использую средство форматирования %q для форматирования строки, экранирующей любые символы, которые могут быть проблемой как часть команды, но при вызове printf через xargs printf утверждает, что не поддерживает %q. Я думаю, что это, возможно, потому, что существует более одной версии printf, но я не совсем уверен, как это решить.

Любая помощь будет оценена по достоинству, даже если решение полностью отличается от того, что я начал :) Спасибо!

Обновление Вот результат, который я получаю в MacOS:

$ cat config.json | xargs -0 printf %q
printf: illegal format character q

Мой файл JSON выглядит так:

{
    "hue_host": "192.168.1.2",
    "hue_username": "myUsername",
    "port": 12000,
    "player_group_config": [
        {
            "name": "Family Room",
            "player_uuid": "ATVUID",
            "hue_group": "3",
            "on_events": ["media.play", "media.resume"],
            "off_events": ["media.stop", "media.pause"]
        },
        {
            "name": "Lounge",
            "player_uuid": "STVUID",
            "hue_group": "1",
            "on_events": ["media.play", "media.resume"],
            "off_events": ["media.stop", "media.pause"]
        }
    ]
}

person Mark Stickley    schedule 14.05.2019    source источник
comment
cat file.json | xargs -0 printf %q у меня работает на debian9. Можете ли вы предоставить дополнительную информацию и пример вывода из канала до команды xargs?   -  person Fredrik Pihl    schedule 14.05.2019
comment
Разместите свой контент в формате JSON и покажите нам точный требуемый результат. Используйте 1_   -  person Inian    schedule 14.05.2019
comment
Спасибо за помощь! Вопрос отредактирован, чтобы включить запрашиваемую информацию. Желаемый результат - это файл JSON, помещенный в строку конфигурации среды как часть команды, которую я хочу запустить для выполнения моего сценария...   -  person Mark Stickley    schedule 14.05.2019
comment
Попробуйте xargs -0 bash -c printf %q — возможно, printf доступен только как встроенная оболочка вашей системы.   -  person cxw    schedule 14.05.2019
comment
Отсутствие спецификатора формата %q для printf указывает на более старую версию Bash.   -  person tripleee    schedule 14.05.2019
comment
xargs printf будет запускать /usr/bin/printf, а не встроенную версию bash (поскольку printf выполняется не bash, а xargs), а версия /usr/bin обычно не поддерживает формат %q.   -  person Gordon Davisson    schedule 14.05.2019
comment
Зачем вам нужно что-то заключать в кавычки в выводе JSON, используя printf? Либо он уже правильно процитирован в соответствии с правилами JSON, либо нет - в любом случае цитирование в соответствии с правилами оболочки просто исказит его.   -  person muru    schedule 15.05.2019
comment
@cxw спасибо, похоже, это должно работать, но когда я делаю bash -c, у меня возникают проблемы с printf: ``` $ bash -c printf %q Hello world printf: использование: printf [-v var] формат [аргументы] `` `   -  person Mark Stickley    schedule 20.05.2019
comment
@MarkStickley Извините - забыл кавычки - используйте bash -c 'printf "%q" "Hello"' со всей командой после -c, заключенной в кавычки, здесь ''. -c использует в качестве команды только следующий аргумент, поэтому вся команда должна быть заключена в кавычки, чтобы она анализировалась как один аргумент. mywiki.wooledge.org/WordSplitting   -  person cxw    schedule 20.05.2019
comment
@Shawn, это именно то, что я хочу, спасибо, хотя не могу гарантировать доступность jq :/   -  person Mark Stickley    schedule 21.05.2019


Ответы (1)


Два пути:

  1. Используйте xargs, чтобы выбрать встроенный printf bash вместо исполняемого файла printf(1), вероятно, в /usr/bin/printf (спасибо @GordonDavisson):

    pwr_config=`echo "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync(process.argv[2], 'utf-8'))));" | node - config.json | xargs -0 bash -c 'printf "%q\n"'` npm run start
    
  2. Проще: вам не нужно экранировать вывод команды, если вы заключаете ее в кавычки. Точно так же, как echo "<|>" в порядке в bash, это также должно работать:

    pwr_config="$(echo "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync(process.argv[2], 'utf-8'))));" | node - config.json )" npm run start
    

    Здесь используется более новая форма $(...) вместо `...`, поэтому результатом команды является одно слово, сохраненное как есть в переменной pwr_config.*

  3. Еще проще: если ваш скрипт npm run start заботится о пробелах в вашем JSON, он в корне не работает :). Просто делать:

    pwr_config="$(< config.json)" npm run start
    

    $(<...) возвращает содержимое config.json. Все они хранятся как одно слово ("") в pwr_config, новые строки и все такое.* Если что-то сломается, либо config.json содержит ошибку и ее следует исправить, либо код, который вы выполняете, содержит ошибку. и нуждается в исправлении.

* На самом деле вам не нужны "" рядом с $(). Например, foo=$(echo a b c) и foo="$(echo a b c)" имеют одинаковый эффект. Однако мне нравится включать "", чтобы напомнить себе, что я специально прошу, чтобы весь текст был собран вместе.

person cxw    schedule 20.05.2019
comment
Вау, большое спасибо за ответ и огромное упрощение! Это идеально :D - person Mark Stickley; 22.05.2019