【问题标题】:jq to remove one of the duplicated objectsjq 删除重复的对象之一
【发布时间】:2018-07-31 17:53:05
【问题描述】:

我有一个这样的 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"}
....

【问题讨论】:

  • 但是这些对象中都没有field1...所有内容都将被删除。您需要键入一个实际存在的字段。例如,jq -cs 'unique_by(.cust_name)[]' input.json

标签: json linux jq


【解决方案1】:

对于field1,我怀疑你在输出中得到了什么,因为没有给定名称的键/字段。如果您只是将命令更改为jq -s 'unique_by(.caller_id)',它将为您提供所需的结果,其中包含基于caller_id 键的唯一和排序对象。它将确保每个caller_id 至少有一个对象。

注意:与 @Jeff Mercado 在 cmets 中解释的内容相同。

【讨论】:

  • 你说得对,我的意思是 .caller_id 但我以 field1 为例。我试过 jq -s 'unique_by(.caller_id)' 没问题,请问我是否可以将项目保留在 cust_name !="" ? TIA
  • 我现在有点困惑,如果您可以通过使用输入 json 和预期输出 json 修改您的问题来澄清,我将使用所需的解决方案更新我的答案。
  • 感谢您的回答,我刚刚使用vi删除了“cust_name”:“”的行,现在可以了
【解决方案2】:

如果文件由 JSON 对象的序列(流)组成,那么生成不同对象流的一种非常简单的方法是使用调用:

jq -s `unique[]`

类似的选择是:

jq -n `[inputs] | unique[]`

但是,对于大文件,上述方法在 RAM 和运行时方面可能效率太低。请注意,uniqueunique_by 都需要排序。

更好的选择是利用输入是流这一事实,并避免使用内置的uniqueunique_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(. != [[]]))) 

【讨论】:

    猜你喜欢
    • 2011-02-16
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    相关资源
    最近更新 更多