我有一个像这样的json文件:
{"caller_id":"123321","cust_name":"abc"}
{"caller_id":"123443","cust_name":"def"}
{"caller_id":"123321","cust_name":"abc"}
{"caller_id":"234432","cust_name":"ghi"}
{"caller_id":"123321","cust_name":"abc"}
....
我尝试过:
jq -s 'unique_by(.field1)'
但是这将删除所有重复项,我希望仅保留其中一项,以获取如下文件:
{"caller_id":"123321","cust_name":"abc"}
{"caller_id":"123443","cust_name":"def"}
{"caller_id":"234432","cust_name":"ghi"}
....
答案 0 :(得分:0)
对于Path=
,我怀疑您是否在输出中得到了任何东西,因为没有给定名称的键/字段。如果仅将命令更改为field1
,它将为您提供所需的结果,其中包含基于jq -s 'unique_by(.caller_id)'
键的唯一且经过排序的对象。这样可以确保每个caller_id
至少有一个对象。
注意:与@Jeff Mercado在评论中解释的内容相同。
答案 1 :(得分:0)
如果文件由JSON对象的序列(流)组成,则产生不同对象流的一种非常简单的方法是使用调用:
jq -s `unique[]`
一个类似的选择是:
jq -n `[inputs] | unique[]`
但是,对于大文件,无论是在RAM还是在运行时上,上述效率可能都太低了。请注意,unique
和unique_by
都需要排序。
更好的选择是利用输入是流这一事实,并避免使用内置的unique
和unique_by
过滤器。可以在以下过滤器的帮助下完成此操作,这些过滤器尚未内置但有可能成为内置过滤器:
# emit a dictionary
def set(s): reduce s as $x ({}; .[$x | (type[0:1] + tostring)] = $x);
# distinct entities in the stream s
def distinct(s): set(s)[];
我们现在只需添加:
distinct(inputs)
要实现该目标,只要使用-n命令行选项调用jq。
这种方法还将保留原始顺序。
如果输入是数组,则使用上面定义的distinct
仍然具有不需要排序的优点。对于太大而无法舒适地容纳在内存中的阵列,建议使用jq的流解析器来创建流。
一种可能是分两个步骤(jq --stream .... | jq -n ...
)进行,但最好使用以下“主”程序一步完成(jq -cn --stream ...
):
distinct(fromstream(inputs
| (.[0] |= .[1:] )
| select(. != [[]])))