【问题标题】:Extract count of a string in log file using grep使用 grep 提取日志文件中字符串的计数
【发布时间】:2017-01-10 16:11:12
【问题描述】:

我想获取当前日期的错误日志文件中的异常计数。下面是log sn-p

10.01.2017 14:03:15.517 *Error* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NumberFormatException: For input string: "true"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:441)
    at java.lang.Long.parseLong(Long.java:483)

10.01.2017 14:03:15.516 *INFO* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NumberFormatException: For input string: "true"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:441)
    at java.lang.Long.parseLong(Long.java:483)

09.01.2017 14:03:15.514 *INFO* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message  at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NullPointerException: For input string: "true"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:441)
    at java.lang.Long.parseLong(Long.java:483)

如果我运行以下 grep 命令,它会给我结果

$ grep -c $(date +"%d.%m.%Y") error.log

但是当我尝试使用 'Exception' 关键字进一步搜索它时,它不起作用。下面是命令

$ grep -c $(date +"%d.%m.%Y") error.log | grep 'Exception'

其次,我想获取相同异常行的计数,我正在使用此命令

$ grep  $(date +"%d.%m.%Y") error.log | sort | uniq -c | sort -r

但在例外情况下,我在 1 月 10 日日期的两行都得到“1”“1”计数,因为毫秒(14:03:15.517,14:03:15.516)值不同。有什么方法可以跳过第二个值并找到行数

输出:-

 1 10.01.2017 14:03:15.517 *Error* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
      1 10.01.2017 14:03:15.516 *Error* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)

预期输出:-

2 10.01.2017 14:03:15 *Error* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)

【问题讨论】:

  • 你的预期输出是什么?
  • 因为包含字符串exception的行是与您当前日期匹配的下一行
  • 那么我如何在linux中使用命令来获取它
  • 正则表达式中的 . 表示任何字符,因此如果您尝试 grep 查找像 10.01.2017 这样的日期,它实际上将匹配像 010201320175 这样的任何字符串。您需要转义 .s 或使用 -F 进行字符串匹配而不是正则表达式匹配,并考虑添加其他构造以避免其他部分匹配。

标签: linux shell awk grep


【解决方案1】:

如果您使用GNU grep,请使用-A 标志来显示与给定模式之后匹配的行,即

grep -A 2 "$(date +"%d.%m.%Y")" file 
10.01.2017 14:03:15.517 *Error* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NumberFormatException: For input string: "true"
--
10.01.2017 14:03:15.516 *INFO* [10.207.11.183 [1481704390201] POST /bin/flipkart/cart.GetCart.json HTTP/1.1] org.apache.cxf.services.StockServiceService.StockServicePort.StockService Inbound Message at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NumberFormatException: For input string: "true"

上面的命令只显示了date后面的两行,现在要获取计数,使用

grep -A 2 "$(date +"%d.%m.%Y")" file | grep -c "Exception"
2

使用两个awk的组合

awk -v dateToSearch="$(gdate +"%d.%m.%Y")" '$0 ~ dateToSearch{line[NR+2]}NR in line' file | awk -F'[:.]' '{unique[$4]++}END{for (i in unique) print i, unique[i]}' 
NumberFormatException 2

我将分解Awk 中使用的逻辑以便更好地理解。

  • 输入行在awk 中一次解析一行,以搜索今天的日期,使用带有-v 标志(特定于awk)的变量,并将其设置为今天的日期。李>
  • 命令$0 ~ dateToSearch{line[NR+2]}NR in line 的主体执行以下操作; $0 代表整行,regEx 模式匹配使用 ~ 运算符完成,以匹配包含今天日期的行。一旦匹配,{} 中的命令就会被执行。这只是意味着,在模式匹配之后打印第二行(类似于grep -A 2 ..)。 NRawk 中的一个特殊变量,它在处理文件时跟踪记录号(行号)。因此,当匹配模式时,NR 被设置为该行,因此NR+2 在匹配后打印第二行。

  • 可以避免流水线化的awk,即在| awk .. 之后,并将其合并为单个awk,这可能会使命令变得复杂。所以基本上第二部分所做的是,-F'[:.]' 将输入字段分隔符设置为出现:.,以便可以通过单个数字访问字段/列(例如$1$2 等)。

  • 1234563见过。因此,一旦处理完所有行,数组就会包含所有异常类型及其计数。
  • awk 中的 END{} 子句在处理完所有行后运行,因此使用它来打印计数和唯一异常标识符。

【讨论】:

  • 嗨 Inian,谢谢它的工作原理。您能否就这个问题的第二部分提供一些想法。即第二件事是我想为此获取相同异常行的计数,我正在使用此命令 $ grep $(date +"%d.%m.%Y") error.log |排序 |唯一的-c | sort -r 但在例外情况下,我在 1 月 10 日日期的两行都得到“1”“1”计数,因为毫秒(14:03:15.517,14:03:15.516)值不同。有什么方法可以跳过第二个值并找到行数
  • 你能更新一下你希望输出的准确程度吗?
  • @user2142786:您希望异常计数独立于今天的日期吗?
  • 不,我不希望它独立于今天的日期。我想要今天日期和异常文本的唯一异常计数。
  • $ awk -v dateToSearch="$(date +"%d.%m.%Y")" '$0 ~ dateToSearch{line[NR+2]}NR in line' error.log | awk -F'[:.]' '{unique[$4]++}END{for (i in unique) print i, unique[i]}' 如果你能解释一下这个命令是如何工作的,那就太好了'我是 shell 脚本的新手
【解决方案2】:

正确的方法是在段落模式下使用 awk(即由RS=<null> 提供的空白行分隔的文本块):

$ awk -v date="$(date +"%d.%m.%Y")" -v RS= '$1==date && /Exception/{c++} END{print c+0}' file
2

请注意,由于我们在第一个字段上使用完全匹配和字符串比较,因此这种方法不可能在日期上出现错误匹配。

【讨论】:

    猜你喜欢
    • 2012-11-05
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多