单个“jq”命令写入不同的文件

单个“jq”命令写入不同的文件

我有一个 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.txttype1type 3city

如果文件type_1.txttype_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

相关内容