使用grep提取日志文件中字符串的计数

时间:2017-01-10 16:11:12

标签: linux shell awk grep

我想在当前日期的错误日志文件中获取异常计数。下面是日志片段

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

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

输出: -

 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)

2 个答案:

答案 0 :(得分:3)

如果您使用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等。

  • 因此,为了跟踪异常的唯一计数,我使用一个异常名称(行中为$4)的数组创建一个哈希表作为索引并增加异常的出现次数,如它被看到了。因此,一旦处理完所有行,该数组就包含所有具有计数的异常类型。

  • END{}中的awk子句在处理完所有行后运行,因此使用它来打印计数和唯一的异常标识符。

答案 1 :(得分:2)

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

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

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