【问题标题】:How to analyse file on linux如何在Linux上分析文件
【发布时间】:2018-03-31 15:48:27
【问题描述】:

我有一个格式如下的文件:

{"report":[{"call_time":"2018-03-31 00:10:13","number":"01232802624","CLI":"7941232455","name":null,"目的地":null,"状态":"已回答","持续时间":"27:30"}, {"call_time":"2018-03-31 00:12:21","number":"01233802632","CLI":"7831233003","name":null,"destination":null,"status": "已回答","持续时间":"7:48"}, {"call_time":"2018-03-31 00:51:16","number":"0123802642","CLI":"7711123367","name":null,"destination":null,"status": "已回答","持续时间":"0:57"}, {"call_time":"2018-03-31 01:50:33","number":"012342802624","CLI":"7812386544","name":null,"destination":null,"status": "已回答","持续时间":"9:54"}, {"call_time":"2018-03-31 16:29:38","number":"01232802642","CLI":"7741230002","name":null,"destination":null,"status": "已回答","持续时间":"0:13"}], "summary":{"Total_Calls":"3,862","Answered_Calls":"3,834","Answered":"3,922:58","Calls_Answered":"99.1%","ACD":"8:00"} "结果":1}

我需要为每个“数字”过滤掉除最新十行之外的所有内容(最好是按时间计算的最新 10 行),并打印平均持续时间。

预期的输出类似于:

2018-03-31 00:10:13 01232802624 27:30
01232802624 Average 27:30

2018-03-31 00:12:21 01233802632 7:48
01233802632 Average 7:48

2018-03-31 00:51:16 0123802642 0:57
2018-03-31 16:29:38 0123802642 0:13
0123802642 Average: 0:30

欢迎提出任何想法...我已经使用 sed、grep 和 awk 尝试了几个小时,但无法做到这一点...我的代码和结果到处都是。我正在努力在网上找到任何解决方案。

【问题讨论】:

  • 请在您的帖子中也显示代码标签中的预期输出。
  • 还是不清楚,请使用帖子中的 {} 按钮将示例包装在代码标签中。

标签: linux awk sed grep


【解决方案1】:

jq 是处理 JSON 的强大工具。它在jq Manual 上有很好的文档。

jq 对解析持续时间的支持有点欠缺,所以你可能不得不在那里使用其他东西,而且我不确定你想要的确切输出格式,所以我没有给出完整的解决方案。

这是一个例子,也许它可以帮助你朝着正确的方向前进:

$ jq '.report | group_by(.number) | .[][-10:] | [.] | map({number: .[0].number, calls: map({call_time: .call_time, duration: .duration})}) | .[]' < data
{
  "number": "01232802624",
  "calls": [
    {
      "call_time": "2018-03-31 00:10:13",
      "duration": "27:30"
    }
  ]
}
{
  "number": "01232802642",
  "calls": [
    {
      "call_time": "2018-03-31 16:29:38",
      "duration": "0:13"
    }
  ]
}
{
  "number": "01233802632",
  "calls": [
    {
      "call_time": "2018-03-31 00:12:21",
      "duration": "7:48"
    }
  ]
}
{
  "number": "012342802624",
  "calls": [
    {
      "call_time": "2018-03-31 01:50:33",
      "duration": "9:54"
    }
  ]
}
{
  "number": "0123802642",
  "calls": [
    {
      "call_time": "2018-03-31 00:51:16",
      "duration": "0:57"
    }
  ]
}

解释:

  1. .report:取根对象的report
  2. group_by(.number):按number 键的值分组
  3. .[][-10:]:对于每个组 (.[]),只保留最后 10 项 ([-10:])
  4. [.]:嵌套在一个数组中,让下一个命令快乐
  5. map(...):将组数组映射到对象数组
  6. .[]去掉不必要的嵌套

这是另一种变体,输出以制表符分隔:

$ jq -r '.report | group_by(.number) | .[][-10:] | map([.number, .call_time, .duration]) | .[], [] | join("\t")' < data
01232802624 2018-03-31 00:10:13 27:30

01232802642 2018-03-31 16:29:38 0:13

01233802632 2018-03-31 00:12:21 7:48

012342802624    2018-03-31 01:50:33 9:54

0123802642  2018-03-31 00:51:16 0:57

解释:

  1. .report:取根对象的report
  2. group_by(.number):按 number 键的值分组
  3. .[][-10:]:对于每个组 (.[]),只保留最后 10 项 ([-10:])
  4. map(...):将对象映射到数组项
  5. .[], []:添加一个额外的数组以在组之间创建空间
  6. join("\t"):用制表符连接每个数组的元素

【讨论】:

  • 谢谢你——太好了!它几乎就在那里 - 只是一个表格或列格式,因此可以对其进行审查将使其完整......我将与 jq 一起玩,看看我是否能弄清楚这一步 - 如果你碰巧知道它,它会有所帮助。
  • 我已经更新了答案以添加一个输出以制表符分隔的示例。
【解决方案2】:

我没有时间编写整个脚本,但这可以用简单的脚本来完成:

  1. 列出您的数字:在第 7 个字段上 awk,然后排序,然后 uniq。
  2. 为每个选择最后 10 行:使用 grep 和 tail -10 在最后一个结果上循环
  3. 为找到的结果转换持续时间(以秒为单位)。
  4. 做小计和平均持续时间。
  5. 然后打印。

希望有帮助

【讨论】:

    猜你喜欢
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    相关资源
    最近更新 更多