【问题标题】:use unix tools (e.g. sort) over field extracted from line-delimited JSON对从行分隔的 JSON 中提取的字段使用 unix 工具(例如排序)
【发布时间】:2015-08-26 02:46:49
【问题描述】:

jq 之类的工具对于以声明方式从 line-delimited JSON 中提取和过滤内容非常有用。但是,它似乎需要将所有对象放入内存中以执行诸如排序之类的操作,并且通常利用现有的 *NIX 工具来处理 JSON 中的一个或多个字段可能很有用同时保留原始 JSON blob。

例如,给定来自 Twitter API 的行分隔 JSON,我想按时间戳对推文 JSON blob 进行排序。这可以通过将 Twitter 日期格式转换为 ISO8601(其字典顺序和时间顺序相同)、在 JSON 推文 blob 前面加上该日期、将流传递给 GNU sortcutting 来删除前置日期。

虽然可以使用mkfifopaste 来实现这一点,但我希望通过使用jq 来获得更简洁的解决方案。

【问题讨论】:

    标签: json unix twitter jq


    【解决方案1】:

    可以使用以下命令对 Twitter JSON blob 流进行排序:

    jq -r '(.created_at | strptime("%a %b %d %H:%M:%S +0000 %Y") | todate) + "\t" + tostring' |
    sort -k1,1 |
    cut -f2
    

    对于每个 JSON blob,jq 命令解析“created_at”字段并输出 ISO8601 日期,后跟一个制表符,然后是原始 JSON(不包含制表符或换行符)。 --raw-output/-r 标志确保这不是 JSON 编码的,而是作为原始文本输出。然后,流由 GNU sort 或等效项排序,单独的 JSON blob 由 cut 重新调整。

    【讨论】:

    • 原来可以使用字符串格式化简写jq -r '"\(.created_at | strptime("%a %b %d %H:%M:%S +0000 %Y") | todate)\t\(.)"'
    【解决方案2】:

    jq 可以轻松与其他命令行工具一起使用这一事实确实是 jq 的优势之一,但不再需要使用“slurp”选项(--slurp 或 -s)来完成诸如描述的那个(即,减少 JSON 实体的输入流)。关键是 jq 1.5 版中新的“输入”过滤器。

    为了说明如何使用“输入”来避免将输入文件读入内存,请考虑查找 JSON 实体文件的最大值的任务。这是一种解决方案:

    $ jq -n 'reduce inputs as $i (null; [., $i] | max)'
    

    注意这里需要 -n 选项。

    总之,使用 jq 1.5,可以通过一次读取一个 JSON 实体流(例如可能包含在文件中)轻松处理 JSON 实体流,无论每个输入实体本身是否在一行上。关键是使用“输入”和“-n”选项。

    类似地,现在也可以逐行处理非常大的文本文件,同时仍然能够执行一些缩减操作;这将使用 -R 选项以及 -n 和 inputs 来完成。

    【讨论】:

    • 但是仍然需要管道或 slurping 来实现全局重新排序功能(例如,对 JSON 文件进行排序)。
    • 不。尝试使用 JSON blob 流作为输入:jq -n '[inputs] |排序'
    • 附注当然,写 [inputs] 会导致整个输入被读入内存,但在实践中,更可能写类似 [inputs | filter],在这种情况下,只有过滤后的输入数组会保留在内存中。
    • 但是jq -n '[inputs] | sort 没有有效地啜饮吗?它的内存使用情况似乎表明了这一点!
    猜你喜欢
    • 2013-06-02
    • 2014-04-18
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    相关资源
    最近更新 更多