LINUX.ORG.RU

bash подстановка переменных в *.json шаблон

 ,


0

1

Здравствуйте! Столкнулся с проблемой читаемости собственного скрипта, а именно: внутри скрипта создавал json-файлы, в которых сидели переменные считаемые во время работы. Делалось это через:

cat > file.json << EOF
{
#тело-json-файла, я знаю, что в json не место комментариям ;-)
"for_example": "$TEST"
}
EOF

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

Суть: считать шаблон json-файла, в котором нужным образом расставлены переменные, и записать с применением уже высчитанных переменных новый json.

В попытках хоть что-то сделать с перенаправлениями родилось чудовище, что мир сожрало вот это: < $PATH/file.json > new-file.json

Понимаю, что можно замонстрячить функцию, но думалось и виделось это каким-нибудь лаконичным способом. Пытался в перенаправления, но что-то сложно они мне даются. Хоть и читал уже с 3 или 4 раза.

Помогите, пожалуйста, дилетанту(критикуйте, что не изучаю маны, что плохо формулирую запросы в гугл и прочее, но мне хочется увидеть хоть пару примеров, чтобы понять где я ошибаюсь и что делаю не так) :) Либо направьте в нужном направлении и дальше я самостоятельно изучу вопрос(что и делал раньше, не прибегая к запросам в интернет как сейчас. Честно)).

Ответ на: комментарий от vodz

Хммм, jq пользовался, но не знал, что так можно значения подставить. Спасибо!

Сразу же столкнулся с проблемой, если у меня есть одно слово внутри json, к примеру «value», но попадается оно дважды. Как мне их разделить при обращении jq к файлу? Из того, что нашёл сам - выходит, что опять бегать на костылях городить велосипед из заранее заготовленного массива и подставлять в нужном месте, т.е. в попытке догнать «лаконичность» я сделаю стену текста в замен конструкции, что указал в топике.

apeshand ()
Ответ на: комментарий от apeshand

У тебя JSON статичный с подставляемыми переменными, или трансформируется в зависимости от чего-нибудь (добавляются/убираются фрагменты или порядок)?

В первом случае вполне достаточно использованного тобой heredoc, даже когда их нужно несколько.

Во втором есть смысл заморочиться с jq, чтобы потом не утонуть в костылях на баше.

blexey ★★★★★ ()
Ответ на: комментарий от blexey

json статичен. Их несколько, но не суть.

Heredoc из того, что вижу, опять огород городить, если я правильно понял.

envsubst пока кажется около вменяемым вариантом разве, что требует export value=$value внутри функций.

Можно обойти общей функцией с массивом из названий функций ))

Уххх блииин, хотел же жисть упростить ) А получилось, что кандалы сменил)

Спасибо Вам за помощь в любом случае. Интересно будет попробовать разные варианты. Единственный враг/противник этому - время.

apeshand ()

Суть: считать шаблон json-файла, в котором нужным образом расставлены переменные, и записать с применением уже высчитанных переменных новый json.

тут envsubst подходит лучше

исходный файл:

{"example": {
  "id": "env",
  "value": "Envs",
  "envs": [
    {"env": "Shell", "value": "$SHELL" },
    {"env": "Lang", "value": "$LANG" },
    {"env": "Display", "value": "$DISPLAY" }
  ]
}}

Перевариваем его

envsubst < example.json 

Получаем

{"example": {
  "id": "env",
  "value": "Envs",
  "envs": [
    {"env": "Shell", "value": "/bin/bash" },
    {"env": "Lang", "value": "ru_RU.UTF-8" },
    {"env": "Display", "value": ":0.0" }
  ]
}}

WoozyMasta ()
Ответ на: комментарий от WoozyMasta
EXP1 () {
	for ARR in "$@"
	do
	export $@="$@"
done
}

FUNC () {
	local VARS=(value1 value2 value3)
	EXP1 VARS
	value1=$[10#$num1 / 2]
	value2=$[10#$num2 / 2]
	value3=$[10#$num3 / 2]
}

А если я попробую так? Меня током не ударит не завалит ошибками?:) Просто нет желания создавать временный файл.

apeshand ()
Ответ на: комментарий от apeshand

Хммм, jq пользовался, но не знал, что так можно значения подставить. Спасибо!

Сразу же столкнулся с проблемой, если у меня есть одно слово внутри json, к примеру «value», но попадается оно дважды.

Вам бы книжки писать. Куча эмоций и воды, а что собственно не так — понять трудно. Да хоть сколько угодно. Переменная она и в Африке переменная.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

По делу:

#!/bin/bash
EXP1 () {
	for ARR in $@
	do
	export $@="${@}"
done
}

FUNC () {
	A1=001
	A2="test_"$A1
	A3=003
	A4=Test
	A5=text
	VARS=(A1 A2 A3 A4 A5 A6)
	EXP1 ${VARS[*]}
	envsubst < ex1.json > res.json
}

FUNC
{"example": {
   "id": "test",
   "value": "test",
   "test": [
     {"test": "A1", "value": "$A1" },
     {"test": "A2", "value": "$A2" },
     {"test": "A3", "value": "$A3" },
     {"test": "A4", "value": "$A4" },
     {"test": "A5", "value": "$A5" }
   ]
 }
}
{"example": {
   "id": "test",
   "value": "test",
   "test": [
     {"test": "A1", "value": "001" },
     {"test": "A2", "value": "test_001" },
     {"test": "A3", "value": "003" },
     {"test": "A4", "value": "Test" },
     {"test": "A5", "value": "text" }
   ]
 }
}

По какой-то причине при использовании EXP1 () срезался параметр последний, потому в VARS их 6 при использовании 5 в действительности.

apeshand ()
Ответ на: комментарий от apeshand

По какой-то причине при использовании EXP1 () срезался параметр последний, потому в VARS их 6 при использовании 5 в действительности.

Лучше так вообще не писать. Безопасность вашего кода никуда не годится. И вообще, в чём проблема указать всё сразу как export?

export \
A1=001 \
A2=test_$A1

vodz ★★★★★ ()
Ответ на: комментарий от apeshand

Помогите тогда понять

Если бы еще вас понять, что у вас не так с A6. Вы его сами написали, оно присвоится как пустое, а в json-коде оно не используется и потому ничего страшного не произошло и я не вижу проблему.

«безопасность»

Вот это ${D[*]} формирует вначале строку с первым символом из IFS как разделитель. Но так как юзается без кавычек, то она сразу же разбивается с интерпретированием как отдельные аргументы. Не пишите так. Лучше тут будет "${D[@]}" (вот так, с двойными кавычками). Далее в функции не надо юзать @ - это опять же интерпретирует аргументы перед подстановкой для подсчёта циклов. Вообще опустите.

vodz ★★★★★ ()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от anonymous

В Вашем споре с @vodz - нашёл решение. Проблема изначально была в замене имени переменных на их содержимое в *.json-файле. Я не знал как это сделать «красиво».

Спасибо Вам обоим.

apeshand ()
Ответ на: комментарий от vodz

Пример будет нагляднее:

#!/bin/bash
EXP1 () {
	for ARR in $@
	do
	export $@="${@}"
done
}

FUNC () {
	A1=001
	A2="test_"$A1
	A3=003
	A4=Test
	A5=text
	VARS=(A1 A2 A3 A4 A5)
	EXP1 ${VARS[*]}
	envsubst < ex1.json > res.json
}

FUNC
{"example": {
   "id": "test",
   "value": "test",
   "test": [
     {"test": "A1", "value": "001" },
     {"test": "A2", "value": "test_001" },
     {"test": "A3", "value": "003" },
     {"test": "A4", "value": "Test" },
     {"test": "A5", "value": "A1" }
   ]
 }
}

Взамен $A5 пришло название от A1.

apeshand ()
Ответ на: комментарий от anonymous

А сами переменные могут вычисляться хрен-знает-где в скрипте.

Да на здоровье. Если функция работает со своими переменными, то правильнее было б их делать в той функции как local. Если эта такая хитрая функция, которая не информирует другие о подготовке переменной для экспорта, то либо declare -g, либо соотсвенно export либо пусть возвращает строку value, а экспортировать будет та функция, которая знает список переменных, которые надо экспортировать.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Да ну на хрен вас обоих :)

Пишете какую-то тонкость архитектуры (один пишет костыль для уже существующего export, второй обсуждает реализацию этого костыля), которую без видения всей архитектуры обсуждать не имеет смысла, и выглядит это как форменное извращение.

anonymous ()
Ответ на: комментарий от apeshand

Взамен $A5 пришло название от A1.

Потому что вы так и не переписали правильно как я вам говорил, а получилось чушь. Допишите echo перед export в EXP1() и поймёте.

Но не для данного случая, а вообще правильный код был бы

#!/bin/bash
EXP1 () {
        for ARR
        do
#         echo export $ARR="${!ARR}"
        export $ARR="${!ARR}"
       done
}

FUNC () {
        A1=001
        A2="test_"$A1
        A3=003
        A4=Test
        A5=text
        VARS=(A1 A2 A3 A4 A5)
        EXP1 "${VARS[@]}"
        envsubst < ex1.json > res.json
}

FUNC

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Спасибо большое, что расписали, но я отвечал на Ваш комментарий - конкретно про неиспользуемое A6 и привёл этому пример.

Спасибо всем! @vodz @bl @blexey @WoozyMasta и анонимному товарищу.

Вопрос, по конкретно этой проблеме, исчерпывающе закрыт.

apeshand ()