假設我有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=~/foo
、var2=$var1
、var3=$(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"}