是否有任何有效和快速的方法可以在日志文件中捕获两个匹配项?



我想了解一些想法。

我的情况是:我的Linux服务器上有大量的日志,它们很大,里面也有很多东西。我只想从日志中获取带有时间戳的登录名和电子邮件地址,并将它们收集到.txt文件中。

示例日志:

[...]
2019-07-21 03:13:06.939 login 
[things not needed between the two]
(mail=>example@mail.com< method=>email< cmd=>login<)
[...]

示例输出:

************** 2019-07-21 **************
2019-07-21 03:13:06.939 login
example@mail.com
2019-07-21 06:22:19.424 login
example@mail.com
2019-07-21 12:10:23.665 login
example@mail.com
2019-07-21 14:26:19.068 login
example@mail.com
************** 2019-07-22 **************
2019-07-22 08:01:50.157 login
example@mail.com
2019-07-22 08:12:35.504 login
example@mail.com
2019-07-22 09:10:35.416 login
example@mail.com

为了实现这一点,我现在使用这个:

for i in $(ls); do echo "" && printf "************** " && cat $i | head -c 10 && printf " **************n"; while read line; do echo $line | grep "login"; echo "$line" | grep -h -o -P '(?<=mail=>).*?(?=<)'; done < $i; done >> ../logins.txt

for循环正在遍历文件,cat $i | head -c 10将获得日期(因为这是每个日志中的第一件事(,while循环逐行读取文件,grep登录名和仅邮件地址(grep介于"mail=>"<之间(。最后输出到logins.txt。

当它工作时,我发现它非常非常慢,因为它执行了很多命令。(我们在这里谈论的是2年的原木(而且它看起来也很脏。

我真的认为有一种有效的方法可以做到这一点,但我真的不明白那会是什么

对于awk,使用-F选择邮件帐户:

sep='************************'
awk -v sep="$sep" -F '(mail=>|<)' '
FNR==1 { printf("%s %s %sn", sep, substr($0,0,10), sep)}
/mail=>/ {print $2}
/login *$/ {print}
' *

当你有额外的要求并且想要使用循环时,考虑

for f in *; do
sed -nr '
1s/(.{10}).*/********* 1 **********/p;
/login *$/p;
s/.*mail=>([^<]*).*/1/p
' "${f}"
done

awk会做得很好。您可以告诉它只有当该行与特定正则表达式匹配时才打印该行。类似于:

awk '$0~/[0-9]{4}-[0-9]{2}-[0-9]{2}|(mail=>/{print $0}' * > output.log 

更新:注意到你只是想要电子邮件。在这种情况下,两块就足够了。在第二个块中,我们按字符<>进行拆分,然后从结果数组的索引2中检索电子邮件。

awk '$1~/^[0-9]{4}-[0-9]{2}-[0-9]{2}/{print $0}$1~/^(mail=>/{split($1,a,"[<>]");print a[2]}' * > output.log

这个awk说:

  1. 如果我们正在读取的行的第一个字段(其中字段由awk默认的空格字符分隔(以nnnn-nn-nn:$1~/^[0-9]{4}-[0-9]{2}-[0-9]{2}/格式的日期开始
  2. 然后打印整行{print $0}
  3. 如果我们正在读取的行的第一个字段以字符(mail=>:$1~/^(mail=>/开头
  4. 然后用字符<>将第一个字段拆分为一个名为a:split($1,a,"[<>]")的数组
  5. 然后打印数组中的第三项(索引2(:print a[2]
  6. 对于当前目录中的所有文件:*
  7. 不打印到命令行,而是将输出发送到文件:> output.log

最新更新