首页 > 解决方案 > 日志文件的有效grep

问题描述

我有一个日志文件,其中包含很多关于这种格式的行:

10.87.113.12 - - [2019-12-09T11:41:07.197Z] "DELETE /page/sub1.php?id=alice HTTP/1.1" 401 275 "-" "alice/7.61.1"
10.87.113.12 - - [2019-12-09T11:41:07.197Z] "DELETE /page/sub1.php?id=alice HTTP/1.1" 401 275 "-" "alice/7.61.1"
10.87.113.12 - - [2019-12-09T11:43:51.008Z] "POST /page/sub2.php?id=alice&jw_token=07e876afdc2245b53214fff0d4763730 HTTP/1.1" 200 275 "-" "alice/7.61.1"

我的目标很简单:我想输出 Alice 的 jw_token,仅此而已。

所以,我的逻辑是我需要找到包含id=alice和状态码 200 的行,然后返回jw_token.

我实际上设法做到了这一点,但只有这条线的绝对怪物:

$ grep "id=alice" main.log | grep 200 | grep -o "n=.* " | sed "s/.*=//g" | sed "s/ .*$//g" | uniq
07e876afdc2245b53214fff0d4763730

这看起来很可怕,并且可能会在许多事情上中断(例如,如果“200”恰好出现在线上的其他任何地方)。我知道grep -P可以稍微清理一下,但不幸的是,我的 Mac 上没有该标志。

我还通过包含 Python 来做到这一点,如下所示:

cat << EOF > analyzer.py
import re

with open('main.log') as f:
    for line in f:
        if "id=alice" in line and " 200 " in line:
            print(re.search('(?<=jw_token\=).*?(?=\s)', line).group())
            break
EOF
python3 analyzer.py && rm analyzer.py

grep(这实际上比前一行和快得多(数量级)sed。为什么?)

当然,有一些方法可以让这变得更干净、更漂亮。如何?

标签: regexlogginggrep

解决方案


您可以通过只使用一个 grep 和 sed 来实现此命令,

grep -E 'id=alice&jw_token=.* HTTP\/1.1" 200' main.log|sed -E 's/.*id=alice&jw_token=([a-zA-Z0-9]+).*/\1/'|uniq

这里第一部分grep -E 'id=alice&jw_token=.* HTTP\/1.1" 200' main.log将过滤掉所有没有 alice 且没有状态 200 的行,下sed -E 's/.*id=alice&jw_token=([a-zA-Z0-9]+).*/\1/'一部分将仅捕获 group1 中的令牌并仅用令牌替换整行。


推荐阅读