我可以使用命令列直接將列出多個變數的檔案轉換為 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"}

相關內容