【问题标题】:Get item and subsequent item based on a property of the first one根据第一个的属性获取项目和后续项目
【发布时间】:2019-10-20 12:41:33
【问题描述】:

我有一个无法更改的第三方工具生成的事件日志文件。因此,这个日志文件是一个巨大的 JSON 数组,其中赔率元素包含元数据,而对包含与元数据关联的正文消息。我希望能够根据元数据拆分文件,按主题将信息聚集在不同的文件中。

我正在 Windows 上处理这个项目,我正在尝试使用批处理文件和 JQ。

数组基本上是这样的:

[
  { "type": "abc123"},
  {"name":"first component of type abc123"},
   { "type": "abc123"},
  {"name":"second component of type abc123"},
  { "type": "def124"},
  {"name":"first component of type def124"},
  { "type": "xyz999"},
  {"name":"first component of type xyz999"},
  { "type": "abc123"},
  {"name":"third component of type abc123"},
  { "type": "def124"},
  {"name":"second component of type def124"},
  { "type": "abc123"},
  {"name":"fifth component of type abc123"},
  { "type": "abc123"},
  {"name":"sixth component of type abc123"},
  { "type": "def124"},
  {"name":"third component of type def124"},
  { "type": "def124"},
  {"name":"fourth component of type def124"},
  { "type": "abc123"},
  {"name":"seventh component of type abc123"},
  { "type": "xyz999"},
  {"name":"second component of type xyz999"}
  ...
]

我知道我只有 3 种类型,所以我想要归档的是为每种类型创建一个文件。类似:

第一个文件

{
  "componentLog": {
       "type": "abc123",
       "information": [
          "first component of type abc123",
          "second component of type abc123",
          "third component of type abc123",
          ...
       ]
     }
}

第二个文件

{
  "componentLog": {
       "type": "def124",
       "information": [
          "first component of type def124",
          "second component of type def124",
          "third component of type def124",
          ...
       ]
     }
}

第三个文件

{
  "componentLog": {
       "type": "xyz999",
       "information": [
          "first component of type xyz999",
          "second component of type xyz999",
          "third component of type xyz999",
          ...
       ]
     }
}

我知道我可以用这个分隔元数据

jq.exe ".[] | select(.type==\"product\")" file.json

然后我尝试计算 index。但 index 只返回包含 select 语句的第一项的索引...所以我不知道如何解决这个问题...

【问题讨论】:

  • “巨大”有多大?能否将 JSON 文件读入内存(例如jq empty file.json)?
  • @peak 文件大小约为 5Gb,因此不能选择内存。我正在使用 JQ,因为 AFAIK 它确实为我传输了文件。
  • @shellter 谢谢你的反馈,但我不明白你的意思是减少样本数据...
  • 如果日志文件对于内存来说太大了,那么很可能其中一个输出文件对于内存来说也太大了。如果是这种情况,那么使用单个 JSON 实体创建如此大的文件有什么意义?为什么不将日志文件分成三个,每个都有一个 JSON 实体流?
  • @peak 另一个组件将上传这些文件并将其转换为弹性搜索的输入。我无法控制整个工作流程,所以我必须提供其他团队需要的东西。

标签: json batch-file jq data-partitioning


【解决方案1】:

以下 bash 脚本有点混乱,因为它假定所有文件(输入或输出)都不适合内存。

如果您还没有在您的计算环境中访问 bash、sed 和 awk,您可能需要考虑安装 或类似的,或者您可以适当地调整脚本,例如使用gawk for Windows,或Ruby for Windows

原始问题中尚未嵌入的另一个主要假设是可以删除 log-type*.tmp 文件和 为“type”的各种值覆盖 log-TYPE.json。

确保将input 设置为适当的输入文件名。

# The input file name:
input=file.json

/bin/rm log-type*.tmp

# Use jq to produce a stream of .type and .name values 
# as per the jq FAQ
jq -cn --stream '
   fromstream(1|truncate_stream(inputs))
   | if .type then .type else .name end'  "$input" |
 awk '
      NR%2 {fn=$1; sub("^\"","",fn); sub("\"$","", fn); next;} 
      { print > "log-type." fn ".tmp"}
'

for f in log-type.*.tmp ; do
    echo formatting $f ...
    g=$(sed -e 's/log-type.//' -e 's/.tmp$//' <<< "$f")
    echo g="$g"
    awk -v type="\"$g\"" '
      BEGIN { print "{\"componentLog\": { \"type\": " type " ,";
      print "\"information\": ["; }
      NR==1 { print; next }
      {print ",", $0} 
      END {print "]}}"; }' "$f" > "log-$g.json"
done

【讨论】:

  • 我注意到这个答案似乎不是 [windows] [batch-file]。您确定答案已考虑到OP的要求吗? Windows 携带awksed 可执行文件通常是不常见的,即使它们携带,它们的语法通常也略有不同。您是否期望他们在 Windows 10 或 Unix 工具中提供 WSL?如果是这样,我希望你提到它。此问题没有附加 [bash] 标签。
  • @peak 您的答案很有用,但由于我必须安装额外的东西,我不会认为它是正确的答案。感谢您花费时间和精力来帮助我。
  • 我想你可能错过了我回答的重点。如果你有这么大的输入文件,并且如果你想使用 jq,那么你将不得不以所示的方式使用 jq。我只是用 awk 等来展示所有的东西,为简单的部分提供指导。正如他们所说,SO 不是编码服务。
  • 我已将此代码用作基础并将其翻译为 NodeJS。使用可写和可读的流媒体。对于节点是npmjs.com/package/node-jq
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2021-10-18
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多