我可以使用命令行直接将列出多个变量的文件转换为 JSON 吗?

我可以使用命令行直接将列出多个变量的文件转换为 JSON 吗?

假设我有file以下内容:

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

eval我知道,如果我使用如下命令,我会将所有这些变量直接存储在我的 shell 上:

$ eval $(cat file)

这样做,我的 shell 将创建$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在 shell 上存储文件变量一样,但不是存储变量,而是生成 JSON 输出。是否可以?我可以使用命令行直接将类似结构的文件转换为 JSON 吗?


我的替代解决方案是开发一个代码(不使用 shell),该代码在该文件中逐个字符地运行,然后我在循环中动态地分离所有内容。但我提出这个问题是因为我想避免使解决方案过于复杂。

答案1

使用组合jo(来自这里)和jq(来自这里),而不创建 shell 变量或根本不让 shell 解释该文件:

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,该文件不使用 shell 扩展功能(如var1=~/foovar2=$var1var3=$(uname)...)并且值是以 UTF-8 编码的文本,您可以这样做:

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

根据 shell 语法标记该文件的内容(使用z参数扩展标志,调整(使用Z[flags])以n将未加引号的换行符视为空白并C删除 shell 注释)并使用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"}

相关内容