jq在许多单独的文件中创建输出

时间:2019-01-16 13:21:14

标签: json file group-by jq

给出以下json:

    [
    {"_id":{"$oid":"6d2"},"jlo":"ΕΙ AJSB","dd":"d5f"},
    {"_id":{"$oid":"c6d3"},"jlo":"ΕΙ ALKSB","dd":"5d9"},
    {"_id":{"$oid":"b0cc6d4"},"jlo":"ΕΙ AGHTSB","dd":"1b1"},
    {"_id":{"$oid":"6d2"},"jlo":"ΕPOWΙ AJSB","dd":"d5f"},
    {"_id":{"$oid":"c6d3"},"jlo":"ΕGTΙ ALKSB","dd":"5d9"},
    {"_id":{"$oid":"b0cc6d4"},"jlo":"ΕLKΙ AGHTSB","dd":"1b1"}
    ]

我需要做的是在一个单独的文件中以ll元素的每个离散值输出ta的唯一值,该文件以一对一表示法命名,其中每个dd代码都替换为人类可读的表示法:

d5f:departmentone
5d9:departmentalt
1b1:departshort

所需的输出,以每行为单位,jlo的每个唯一值以及在每个dd元素中发现的次数,因此最终得到如下结果:

first file named departmentone.txt:
ΕΙ AJSB 1
ΕPOWΙ AJSB 1

second file named departmentalt.txt
ΕΙ ALKSB 1
ΕGTΙ ALKSB 1

third file named departshort.txt
ΕΙ AGHTSB 2

我已经尝试过使用map并减少group_by,sort_by,但效果却很差

2 个答案:

答案 0 :(得分:1)

只需要一次调用jq。要将输出分配给单独的文件,可以将这一调用与对awk的单个调用结合使用,或者可以使用如下所示的shell循环。

首先,这是壳管道外观的说明:

jq -r --rawfile dd2name dd2name.tsv -f group.jq input.json |
  while IFS=$'\t' read -r f v ; do echo "$v" >> "$f" ; done

这假定到文件名的映射在名为dd2name.tsv的TSV文件中,并且以下jq程序在group.jq中:

def dict:
  split("\n") | map(select(length>0) | split("\t"))
  | INDEX(.[0]) | map_values(.[1]);

($dd2name | dict) as $dict
| ($dict | keys_unsorted[]) as $dd
| map(select(.dd == $dd))
| group_by(.jlo)
| map("\($dict[$dd])\t\(.[0].jlo) \(length)")[]

顾名思义,dict函数创建一个字典,提供.dd值到文件名的映射。假定INDEX的可用性。如果您的jq没有INDEX,那么现在是升级jq的绝佳时机。否则,可以很容易地从buildin.jq(google:builtin.jq "def INDEX")复制其def,或者您也可以将最后一行替换为:| reduce .[] as $p ({}; .[$p[0]] = $p[1]);

基于awk的解决方案

可以使用以下awk调用来代替上面的while ... done命令:

awk -F\\t 'fn && (fn!=$1) {close(fn)}; {fn=$1; print $2 >> fn}'

调味的季节

如果dd2name.tsv映射文件不包含“ .txt”后缀,则可以根据喜好以各种方式轻松地添加它。

还请注意,以上提出的解决方案进行了一些假设,尤其是.jlo值不包含制表符,换行符或NUL。如果违反了任何这些假设,则需要进行一些调整。

答案 1 :(得分:0)

我将分三遍进行操作,用所需的dd过滤数组并按jlo分组,然后提取数组的第一(保证)项的jlo及其长度:

map(select(.dd == "d5f")) | group_by(.jlo) | map("\(.[0].jlo) \(length)") | .[]

您可以try it here

全bash运行:

jq --arg dd d5f --raw-output 'map(select(.dd == $dd)) | group_by(.jlo) | map("\(.[0].jlo) \(length)") | .[]' yourJsonFile > departmentone.txt
jq --arg dd 5d9 --raw-output 'map(select(.dd == $dd)) | group_by(.jlo) | map("\(.[0].jlo) \(length)") | .[]' yourJsonFile > departmentalt.txt
jq --arg dd 1b1 --raw-output 'map(select(.dd == $dd)) | group_by(.jlo) | map("\(.[0].jlo) \(length)") | .[]' yourJsonFile > departmentshort.txt

假设您有一个名为“ mapping.txt”的文件,其内容如下:

d5f:departmentone
5d9:departmentalt
1b1:departshort

您可以提取这些代码和标签以生成文件:

while IFS=: read -r code label; do
    jq --arg dd $code --raw-output 'map(select(.dd == $dd)) | group_by(.jlo) | map("\(.[0].jlo) \(length)") | .[]' yourJsonFile > "$label".txt
done < mapping.txt