我有一个 JSON 日志文件test.log
:
{"type":"1","fname":"AAA","lname":"bbb" }
{"type":"2","state":"gujarat" }
{"type":"3","city":"ahmedabad" }
{"type":"3","city":"rajkot" }
{"type":"1","fname":"ccc","lname":"ddd" }
我运行以下命令
cat test.log | jq -c "select(.type==\"1\")|{fname:.fname}" > type_1.txt
cat test.log | jq -c "select(.type==\"3\")|{city:.city}" > type_3.txt
单个命令是否可以jq
生成多个输出文件?
我只想对文件运行该jq
命令一次test.log
,并为每种项目类型生成一个输出文件。
答案1
根据手册的IO部分从版本 1.5 开始,jq 只能写入标准输出并将调试消息打印到stderr
.
如果您不想test.log
多次运行 jq (例如,因为它是一个巨大的文件),您可以做的是
jq -c '(select(.type=="1") | {fname:.fname}), (select(.type=="3") | {city:.city})' test.log > temp
# The file 'temp' contains one entry per line.
grep '^{"fname"' temp > type_1.txt
grep '^{"city"' temp > type_3.txt
rm temp
答案2
不是使用jq
,而是使用另一个 JSON 感知处理器 Miller ( mlr
),
mlr --json put -q '
$type == 1 { emit >"type_1.txt", { "fname": $fname } }
$type == 3 { emit >"type_3.txt", { "city": $city } }' file
如果 is ,这将打印一个包含fname
键和文件对应值的 JSON 对象,并同样处理该键的条目。type_1.txt
type
1
type
3
city
如果文件type_1.txt
和type_3.txt
存在,则在此命令向其中写入新数据之前,它们将被截断(清空)。
运行示例:
$ mlr --json put -q '$type == 1 { emit >"type_1.txt", { "fname": $fname } }; $type == 3 { emit >"type_3.txt", { "city": $city } }' file
$ cat type_1.txt
{ "fname": "AAA" }
{ "fname": "ccc" }
$ cat type_3.txt
{ "city": "ahmedabad" }
{ "city": "rajkot" }
答案3
jq
只写入 stdout (或 stderr),因此您需要另一个程序将流拆分为不同的日志文件。
首先,js
使用日志文件字段丰富@nwk的命令。
jq -c '(select(.type=="1") | {"logfile":.type},{fname:.fname}),
(select(.type=="3") | {"logfile":.type},{city:.city})' test.log
您可以将此输出通过管道传输到awk
,它可以获取文件名
jq -c '(select(.type=="1") | {"logfile":.type},{fname:.fname}),
(select(.type=="3") | {"logfile":.type},{city:.city})' test.log |
awk -F"\"" 'BEGIN {FPAT="[^{}:\"]+" }
$1=="logfile" {lf="type_"$2".txt"; next}
{print >> lf}'
答案4
聚会有点晚了。你可以彻底扭转这个问题。jq
您可以创建jq
输出,当作为脚本运行时,写入不同的文件,而不是询问如何写入不同的文件。
这是一个例子:
jq -r \
$' recurse( .children[] ) |
select( (.type="comment") and (.text != null) ) |
"echo \'" + .text + "\' >> " + .author + ".txt" ' < file.json
运行时,会产生如下输出:
echo '<p>Nice! Definitely let me know.</p>' >> user_1.txt
echo '<p>I agree.</p>' >> user_2.txt
然后可以将该输出作为脚本运行以创建单独的文件。没有超出jq
当前 shell 的依赖项,没有管道,也不需要额外的工具。请注意$'
前缀和'
后缀允许在语句\'
内转义echo
。