我有幾個文本檔案,每個檔案里面都有一個標題。例如:
echo 'title: hello' > 1.txt
echo 'title: world' > 2.txt
echo 'title: good' > 3.txt
我有一個名為abc.json的 JSON 檔案,由這樣的 shell 腳本生成:
{
"": [
{
"title": "",
"file": "1"
},
{
"title": "",
"file": "2"
},
{
"title": "",
"file": "3"
}
]
}
我想要的是通過相應文本檔案中的標題更新 abc.json 中的標題值,如下所示:
{
"": [
{
"title": "hello",
"file": "1"
},
{
"title": "world",
"file": "2"
},
{
"title": "good",
"file": "3"
}
]
}
文本檔案和 JSON 檔案位于同一目錄中,如下所示:
? tmp.uFtH6hMC ls
1.txt 2.txt 3.txt abc.json
非常感謝!
更新要求
對不起大家。您的所有答案都非常適合上述要求。
但是我錯過了一些重要的詳細資訊:
文本檔案的檔案名可能包含空格,所以當前目錄應該是這樣的:
? $ gfind . -maxdepth 1 -type f -printf '%P\n' The text file contain one title line and more content.txt The title identifier in the text file is fixed.txt The filename of text file may contain space.txt abc.json文本檔案包括一個標題行,其中包含將被提取到abc.json中的標題值,即意味著“你好”需要放入abc.json的欄位中。標題行,可以是檔案中的任何一行,看起來像. title-identifier是固定的,并通過一個空格與title-value分隔,該空格是title-line中的第一個空格。因此文本檔案內容可能如下所示:
## hellotitle## <title-value>##文本檔案包含一個標題行和更多 content.txt:
## hello world some more content below... ...文本檔案中的標題識別符號是 fixed.txt:
## How are you? some more content below... ...文本檔案的檔案名可能包含 space.txt:
some pre-content... ... ## I'm fine, thank you. some more content below... ...在更新之前,abc.json看起來像這樣:
{ "": [ { "title": "", "file": "The filename of text file may contain space" }, { "title": "", "file": "The text file contain one title line and more content" }, { "title": "", "file": "The title identifier in the text file is fixed" } ] }更新后的abc.json應該是這樣的:
{ "": [ { "title": "I'm fine, thank you.", "file": "The filename of text file may contain space" }, { "title": "hello world", "file": "The text file contain one title line and more content" }, { "title": "How are you?", "file": "The title identifier in the text file is fixed" } ] }再次抱歉...感謝您的耐心等待和大力幫助!
uj5u.com熱心網友回復:
您可以使用 shell 回圈遍歷檔案,提取第二列,創建每個陣列元素,然后將陣列元素流轉換為最終物件:
for f in *.txt; do
cut -d' ' -f2- "$f" | jq -R --arg file "$f" '{title:.,file:($file/"."|first)}';
done | jq -s '{"":.}'
也可以直接去掉shell中的檔案擴展名,這樣jq過濾器就簡單了一點:
for f in *.txt; do
cut -d' ' -f2- "$f" | jq -R --arg file "${f%.txt}" '{title:.,$file}';
done | jq -s '{"":.}'
cut提取標題值,如果檔案結構不同,則必須進行調整,例如使用 grep、sed 或 awk 提取標題,然后將其提供給 jq。
uj5u.com熱心網友回復:
由于.title和.files具有相同的數字,我們可以使用它從輸入中對其進行索引。
因此,使用cut我們可以讀取所有*.txt檔案,拆分 然后獲取倒數第二個欄位,這給出:
cat *.txt | cut -d ' ' -f 1-
hello
world
good
(帶有空格的標題將起作用,因為-f 1-)
使用--arg我們將它傳遞給 jq,然后我們將其決議為一個陣列:
($inputs | split("\n")) as $parsed
現在$parsed看起來像:
[
"hello",
"world",
"good"
]
要更新值,請遍歷陣列中的每個物件,然后通過 using""獲取匹配值(因為陣列是 0-indexed)$parsed.file | tonumber - 1
jq --arg inputs "$(cat *.txt | cut -d ' ' -f 1-)" \
'($inputs | split("\n")) as $parsed
| .""[]
|= (.title = $parsed[.file | tonumber - 1])' \
abc.json
輸出:
{
"": [
{
"title": "hello",
"file": "1"
},
{
"title": "world",
"file": "2"
},
{
"title": "good",
"file": "3"
}
]
}
uj5u.com熱心網友回復:
用于input_filename獲取輸入檔案的名稱,讀取帶有-R標志集的原始內容,并用于select查找要更新的正確專案;一口氣:
jq -Rn --argfile base abc.json '
reduce (inputs | [
ltrimstr("title: "),
(input_filename | rtrimstr(".txt"))
]) as [$title, $file] ($base;
(.[""][] | select(.file == $file)).title = $title
)
' *.txt
如果文本檔案內容的左側部分(示例中的“標題”)應該是動態欄位名稱,您也可以capture:
jq -Rn --argfile base abc.json '
reduce (inputs | [
capture("^(?<key>.*): (?<value>.*)$"),
(input_filename | rtrimstr(".txt"))
]) as [{$key, $value}, $file] ($base;
(.[""][] | select(.file == $file))[$key] = $value
)
' *.txt
輸出:
{
"": [
{
"title": "hello",
"file": "1"
},
{
"title": "world",
"file": "2"
},
{
"title": "good",
"file": "3"
}
]
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/517843.html
標籤:jsonUnixjq
下一篇:如何讓make只編譯?
