shell AWK无法提取邮件日志中的from字段

rjzwgtxy  于 2023-05-18  发布在  Shell
关注(0)|答案(6)|浏览(110)

我试图从邮件日志中提取一些字段,它工作正常,除了下面的消息时失败。

May 10 07:15:04 chitraak sendmail[8558]: 34ABF4Kb008569: from=<"dexter prod" <dexter_noreply@au.edu>>, size=452, class=0, nrcpts=1, msgid=<202305101115.34ABF4Kb946558@chitraak.abc.com>, proto=ESMTP, daemon=MTA, relay=ip-192-68-1-4.ec2.internal [1.2.3.4]

现在,当我执行awk时,它会给出以下输出

cat email | awk '{print $7 " " $NF}'
from=<"dexter [1.2.3.4]

现在所有电子邮件地址的格式都是from= abc@xyz.com。只有此邮件先有自定义名称,然后是电子邮件地址。有人可以告诉一个统一正则表达式,将工作在上面的文本和其余的消息以及。
期望输出

from=<"dexter prod" <dexter_noreply@au.edu>> [1.2.3.4]

由于其他消息在from=<“email”>中没有空格,这就是为什么我的awk命令对这些消息有效的原因。当有空间时,它无法提取。此外,给予上述输出的正则表达式也应该适用于具有格式from=<dexter_noreply@au.edu的字段的其余消息
假设有两条不同格式的消息,如下所示。

May 10 07:15:04 chitraak sendmail[8558]: 34ABF4Kb008569: from=<"dexter prod" <dexter_noreply@au.edu>>, size=452, class=0, nrcpts=1, msgid=<202305101115.34ABF4Kb946558@chitraak.abc.com>, proto=ESMTP, daemon=MTA, relay=ip-192-68-1-4.ec2.internal [1.2.3.4]
May 10 07:15:04 chitraak sendmail[8558]: 34ABF4Kb008569: from=<dexter_noreply@au.edu>, size=452, class=0, nrcpts=1, msgid=<202305101115.34ABF4Kb946558@chitraak.abc.com>, proto=ESMTP, daemon=MTA, relay=ip-192-68-1-4.ec2.internal [1.2.3.5]

实现regex后所需的输出应该如下所示

from=<"dexter prod" <dexter_noreply@au.edu>> [1.2.3.4]
from=<dexter_noreply@au.edu> [1.2.3.4]

我是否需要将它们作为两个独立的正则表达式捕获?

xpszyzbs

xpszyzbs1#

使用逗号标记from=字段的结尾可能是安全的:

awk 'match($0,/from=[^,]*/) { print substr($0,RSTART,RLENGTH), $NF }'
from=<"dexter prod" <dexter_noreply@au.edu>> [1.2.3.4]
from=<dexter_noreply@au.edu> [1.2.3.5]
uyhoqukh

uyhoqukh2#

使用GNUawk
不需要管道cat | awk,它是UUOC,又名Useless Use Of Cat

awk 'BEGIN{FPAT="from=.*>>"}{print $1}' file
from=<"dexter prod" <dexter_noreply@au.edu>>

参见splitting by content
grep

grep -oE 'from=.*?>>' file
from=<"dexter prod" <dexter_noreply@au.edu>>

sed

sed -E 's/.*(from=.*?>>).*/\1/' file
from=<"dexter prod" <dexter_noreply@au.edu>>

Perl

perl -nE 'say $& if /from=.*?>>/' file
from=<"dexter prod" <dexter_noreply@au.edu>>
yws3nbqq

yws3nbqq3#

***第一个解决方案:***使用awkmatch函数,请尝试以下解决方案。使用regex : from=<"[^>]*>>获得OP所需的精确输出。如果找到匹配的regex,则按子字符串打印匹配的值。

awk 'match($0,/: from=<"[^>]*>>/){print substr($0,RSTART+2,RLENGTH-2)}' Input_file

***第二个解决方案:***使用sedE选项,请尝试以下。

sed -E 's/^.*: (from=<"[^>]*>>).*$/\1/' Input_file

***第三个解决方案:***使用GNU grep和regex,并使用\K选项在打印时忘记匹配,使用以下代码。

grep -oP '^.*: \Kfrom=<"[^>]*>>' Input_file

***第四个解决方案:***使用GNU awk及其RSRT功能,尝试以下操作。

awk -v RS=': from=<"[^>]*>>' '
RT && split(RT,arr,": "){
  print arr[2]
}
' Input_file

***第5个解决方案:***仅对所示示例使用简单字段分隔符。

awk -F': |, ' '{print $3}' Input_file
yx2lnoni

yx2lnoni4#

mawk 'BEGIN { ORS = sprintf("%.*s\n",_+= ++_,RS = ">>[^\n]+\n")
               FS = ".+ " (OFS = "from=") }  NF = _'
from=<"dexter prod" <dexter_noreply@au.edu>>

更少regex更硬编码的方式将是

gawk '$(NF = !_ + ($!_ = "from")^_) = $2 ">>"' FS='=|>>.+$' OFS==
from=<"dexter prod" <dexter_noreply@au.edu>>
lsmd5eda

lsmd5eda5#

这个GNUsed应该适用于这两种情况:

sed -E 's/.*(from=.*>.*), size=.* (\[.*\])$/\1/\2/' file
iyr7buue

iyr7buue6#

使用任何sed:

$ sed 's/.*\(from=[^,]*\).* /\1 /' email
from=<"dexter prod" <dexter_noreply@au.edu>> [1.2.3.4]
from=<dexter_noreply@au.edu> [1.2.3.5]

相关问题