Можно ли напрямую преобразовать файл, содержащий список нескольких переменных, в JSON с помощью командной строки?

Можно ли напрямую преобразовать файл, содержащий список нескольких переменных, в JSON с помощью командной строки?

Допустим, у меня есть файл fileсо следующим содержимым:

var1='a random text'
var2='another random text'
var3='a third random text'

Я знаю, что если я использую команду, evalподобную следующей, то я сохраню все эти переменные непосредственно в моей оболочке:

$ eval $(cat file)

Сделав это, моя оболочка создаст $var1, $var2и $var3с их соответствующим содержимым. Зная это, я мог бы вручную сгенерировать JSON следующим образом:

$ JSON="{ \"var1\" : \"$var1\", \"var2\" : \"$var2\", \"var3\" : \"$var3\"}"

И это приведет к корректному JSON:

$ echo $JSON
{ "var1" : "a random text", "var2" : "another random text", "var3" : "a third random text"}

Проблема здесь в том, что я жестко кодирую ключи var1, var2 и var3... В моем случае файл может быть больше и в нем может храниться больше переменных (не только var1, var2 и var3). Я подумал, есть ли простой способ сделать это с помощью командной строки, как это evalделается для хранения переменных файла в оболочке, но вместо сохранения переменных, генерируя вывод JSON. Возможно ли это? Могу ли я напрямую преобразовать файл, структурированный таким образом, в JSON с помощью командной строки?


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

решение1

Используя комбинацию jo(изздесь) и jqизздесь), не создавая переменных оболочки и не позволяя оболочке интерпретировать файл вообще:

jo <file |
jq --arg sq "'" '.[] |= ( ltrimstr($sq) | rtrimstr($sq) )'

Это первое использование joдля создания документа JSON

{
   "var1": "'a random text'",
   "var2": "'another random text'",
   "var3": "'a third random text'"
}

(но в одной строке). Это делается путем интерпретации назначений переменных в вашем файле как пар ключ-значение.

Затем этот jqинструмент используется для удаления одинарных кавычек в начале и конце каждого значения.

Окончательный результат:

{
  "var1": "a random text",
  "var2": "another random text",
  "var3": "a third random text"
}

Это не справится с переносами строк, встроенными в значения. Однако другие специальные символы будут автоматически закодированы в JSON с помощью jo.

решение2

С помощью zshи предполагая, что синтаксис файла совместим с синтаксисом файла zsh, что файл не использует функции расширения оболочки (например var1=~/foo, var2=$var1, , var3=$(uname)...) и что значения представляют собой текст в кодировке UTF-8, вы можете сделать следующее:

tokens=( ${(Q)${(zZ[nC])"$(<file)"}} )

Чтобы токенизировать содержимое этого файла в соответствии с синтаксисом оболочки (используя zфлаг раскрытия параметров, измененный (с помощью Z[flags]) с nцелью рассматривать не заключенные в кавычки символы новой строки как пробелы и Cудалять комментарии оболочки), и удалить один слой кавычек с помощью Qфлага раскрытия параметров.

Затем вы можете передать эти токены чему-то, что может кодировать JSON (обратите внимание на управляющие символы, включая символы новой строки, обратной косой "черты и т. д.):

perl -CA -MJSON -le '
  for (@ARGV) {
    if (/(.*?)=(.*)/s) {
      $h{$1} = $2;
    }
  }
  print encode_json \%h' -- $tokens

Например, один из fileтаких:

var1='a random text' # comment
var2='another'\'' random text'
var3='a third random text'

name=$'St\u00e9phane Chazelas'
empty=
at=@
more=broken\
down"with 1 \\ backslash"
numstring=1.1

Это дает:

{"numstring":"1.1","name":"Stéphane Chazelas","empty":"","more":"brokendownwith 1 \\ backslash","var1":"a random text","at":"@","var2":"another' random text","var3":"a third random text"}

Связанный контент