【问题标题】:unix shell script - search string and formatting to jsonunix shell 脚本 - 搜索字符串并格式化为 json
【发布时间】:2015-04-15 02:02:35
【问题描述】:

我有一个包含多个未格式化的 json 消息的日志文件。 尝试编写一个 shell 脚本在日志中搜索字符串并格式化匹配的 json 并写入文件。

例如:- 在 test.log 文件中,

type_logfile 2015-04-14 18:06:15,284 信息响应日志服务- {"header":{"time":"2015 06:06:13 PM EDT","re​​qId":"1","user":"baskar"}}

type_logfile 2015-04-14 18:06:15,284 信息响应日志服务- {"header":{"time":"2015 06:06:13 PM EDT","re​​qId":"2","user":"raja"}}

type_logfile 2015-04-14 18:06:15,284 信息响应日志服务- {"header":{"time":"2015 06:06:13 PM EDT","re​​qId":"3","user":"baskar"}}

我使用下面的命令,

grep -i "baskar" test.log | grep -o "{\"header\".*" | python -m json.tool > ~/search_result.log

如果搜索仅返回一条 json 消息,则上述命令可以正常工作。如果有多个匹配,这不起作用并抛出以下错误。

无法解码 json 消息。

然而,如果我将匹配的输出重定向到某个文件,然后逐行读取文件以格式化 json 作品。

 grep -i "baskar" test.log | grep -o "{\"header\".*" > ~/search_result.log

while read line
do
    name=$line    
    echo $name | python -m json.tool >> ~/formatted_search_result.log
done < ~/search_result.log

因为,写入临时文件然后从临时文件中读取以格式化 json 会影响性能,因此需要寻找一些有效的方法。

预期的输出是, 当我搜索

grep -i "baskar" test.log

{
    "header": {
      "user": "baskar",
      "reqId": "1",
      "time": "2015 06:06:13 PM EDT"
    }
  }
  {
    "header": {
      "user": "baskar",
      "reqId": "3",
      "time": "2015 06:06:13 PM EDT"
    }

}

谢谢, 巴斯卡尔.S

【问题讨论】:

  • 输出应该是什么样子的?
  • 已经用他预期的输出更新了帖子。

标签: json shell unix


【解决方案1】:

使用jq。鉴于您的示例文本:

sed 's/.*Service - //' file | jq -s .

如果您不想要对象数组,请删除 -s 选项。


你可以过滤jq的输入:

sed -n '/baskar/ s/.*Service - //p' file | jq  .

或者让jq去过滤

sed 's/.*Service - //' file | jq  'select(.header.user == "baskar")'

任一选项产生

{
  "header": {
    "user": "baskar",
    "reqId": "1",
    "time": "2015 06:06:13 PM EDT"
  }
}
{
  "header": {
    "user": "baskar",
    "reqId": "3",
    "time": "2015 06:06:13 PM EDT"
  }
}

【讨论】:

  • 感谢您的回复。我的要求是只获取匹配的 json 格式并写入文件。所以,当我搜索 grep -i "baskar" test.log 时,输出应该是 { "header": { "user": "baskar", "reqId": "1", "time": "2015 06 :06:13 PM EDT" } } { "header": { "user": "baskar", "reqId": "3", "time": "2015 06:06:13 PM EDT" } }
  • 非常感谢。它工作得很棒。反正有没有用&。我尝试了以下方法,但它不起作用。 sed -n '/(baskar\&3)/s/.*Service - //p' 文件 | 。这应该只返回,{ "header": { "user": "baskar", "reqId": "3", "time": "2015 06:06:13 PM EDT" } }
  • 我假设您想匹配 reqId == 3,而不是任何包含 3 的时间戳。我建议:sed 's/.*Service - //' file | jq 'select(.header.user == "baskar" and .header.reqId == "3")'
  • 嗨,我现在有不同的情况。单个 json 中有多个标头,即子 json 元素,例如父 json,并且每个这样的父 json 都有一个公共标头。一个文件中有n个父json。我想针对子 json 搜索一个字符串,并且匹配的子 json 应该与父 json 标头一起返回。我在 JQ 示例中没有找到这个。
  • 请提出一个新问题
猜你喜欢
  • 1970-01-01
  • 2015-12-21
  • 2016-10-28
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-25
  • 2013-06-10
相关资源
最近更新 更多