Допустим, у меня есть файл 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"}