在sed和awk中使用regex

在sed和awk中使用regex,regex,bash,sed,Regex,Bash,Sed,我必须将正则表达式与sed或awk一起使用才能在日志文件中查找内容。日志文件如下所示 Jan 16 08:33:18 mail.knurledwidgets.example.org sendmail[1618]: qhgKT0cN80gSX: to=<user1@company.example.com>, delay=00:00:02, xdelay=00:00:01, mailer=esmtp, pri=193069, relay=mx.company.example.com. [

我必须将正则表达式与sed或awk一起使用才能在日志文件中查找内容。日志文件如下所示

Jan 16 08:33:18 mail.knurledwidgets.example.org sendmail[1618]: qhgKT0cN80gSX: to=<user1@company.example.com>, delay=00:00:02, xdelay=00:00:01, mailer=esmtp, pri=193069, relay=mx.company.example.com. [192.168.123.12], dsn=2.0.0, stat=Sent (OK <sp4jffaeid3FxjPGr@mx.company.example.com>)
Jan 16 08:33:04 mail.knurledwidgets.example.org sendmail[3539]: q5c1SrFqkAZq9b: Milter: connect to filters
Jan 16 08:33:06 mail.knurledwidgets.example.org sendmail[3539]: q5c1SrFqkAZq9b: from=<user1@dont-cross-the-memes.example.com>, size=38065260, class=-30, nrcpts=1, msgid=<gnDSaYSEaP4Yk/.F0EhYbIYcihGO8Vd.dont-cross-the-memes.example.com>, proto=ESMTP, daemon=MTA-v6, relay=proton.dont-cross-the-memes.example.com [192.168.98.234]
^Jan\s\d\d\s(\d\d).*\bfrom\b\=<(.*)>,\s\bsize\b.*
Jan 16 08:33:18 mail.knuredwidts.example.org sendmail[1618]:qhgKT0cN80gSX:to=,delay=00:00:02,xdelay=00:00:01,mailer=esmtp,pri=193069,relay=mx.company.example.com。[192.168.123.12],dsn=2.0.0,stat=Sent(正常)
Jan 16 08:33:04 mail.knuredwidts.example.org sendmail[3539]:q5c1SrFqkAZq9b:Milter:连接到过滤器
一月16日08:33:06 mail.knurledwidts.example.org sendmail[3539]:q5c1SrFqkAZq9b:from=,size=38065260,class=-30,nrcpts=1,msgid=,proto=ESMTP,daemon=MTA-v6,relay=proton.dont-cross-the-memes.example.com[192.168.98.234]
这是日志文件中的三种主要形式。 因为我必须找到收到的邮件,这意味着电子邮件之前有一个“发件人”。 我写过这样的正则表达式

Jan 16 08:33:18 mail.knurledwidgets.example.org sendmail[1618]: qhgKT0cN80gSX: to=<user1@company.example.com>, delay=00:00:02, xdelay=00:00:01, mailer=esmtp, pri=193069, relay=mx.company.example.com. [192.168.123.12], dsn=2.0.0, stat=Sent (OK <sp4jffaeid3FxjPGr@mx.company.example.com>)
Jan 16 08:33:04 mail.knurledwidgets.example.org sendmail[3539]: q5c1SrFqkAZq9b: Milter: connect to filters
Jan 16 08:33:06 mail.knurledwidgets.example.org sendmail[3539]: q5c1SrFqkAZq9b: from=<user1@dont-cross-the-memes.example.com>, size=38065260, class=-30, nrcpts=1, msgid=<gnDSaYSEaP4Yk/.F0EhYbIYcihGO8Vd.dont-cross-the-memes.example.com>, proto=ESMTP, daemon=MTA-v6, relay=proton.dont-cross-the-memes.example.com [192.168.98.234]
^Jan\s\d\d\s(\d\d).*\bfrom\b\=<(.*)>,\s\bsize\b.*
^Jan\s\d\d\s(\d\d)。*\b从\b\=,\s\b大小\b*
我用TextWrangler测试了这个正则表达式。它可以找到所有电子邮件并将其替换为“小时”“电子邮件地址”

然而,当我试图在sed或awk中使用这个正则表达式来编写脚本时。我的代码有一些问题

这是:

#!/bin/bash
sed -E 's/^Jan\s\d\d\s(\d\d).*\bfrom\b\=<(.*)>,\s\bsize\b.*/\1 \2/g' output
#/bin/bash
sed-E的/^Jan\s\d\d\s(\d\d)。*\b从\b\=,\s\b大小\b.*/\1\2/g'输出
我不知道为什么这个代码不起作用。它不能代替任何东西。
如何解决此问题?也许awk是一个更好的选择?

我认为问题在于
\d
语法。这并不是你想的那样。在
sed
中,它后跟与字符匹配的十进制值,因此它会导致正则表达式失败。将它们替换为
[0-9]
,如:

sed -r 's/^Jan\s[0-9]{2}\s([0-9]{2}).*\bfrom\b=<(.*)>,\s\bsize\b.*/\1 \2/g' output

您也可以使用awk(假设可以在“from=上进行匹配),我通常觉得在解析name=value数据的输入时创建一个数组非常方便,该数组允许我通过名称访问值,例如:

$ cat tst.awk
{
    delete n2v
    for (i=1; i<=NF; i++) {
        if ($i ~ /=/) {
            name = value = $i
            sub(/=.*/,"",name)
            sub(/[^=]+=/,"",value)
            gsub(/^<|[>,]+$/,"",value)
            n2v[name] = value
        }
    }

    for (name in n2v) {
        value = n2v[name]
        print ">", name, "=", value
    }
    print "-----"
}
"from" in n2v { print $1, $2, $3, n2v["from"] }

BSD sed中的
-E
开关(例如在mac上)相当于GNU sed中的
-r
开关。我认为这是正确的。但是它在我的mac上不起作用……但非常感谢您的帮助:)@YufeiHan The
\s
(空格)和
\b
(单词边界)元字符在你的sed版本中不起作用。谢谢!它起作用了!顺便问一下,你知道为什么我的
sed
不起作用吗?哇……真是太令人印象深刻了……因为我刚开始学习正则表达式和sed东西……无论如何,我会尽我最大的努力去理解。sed不是你需要花时间学习的东西。它是非常有用的功能是简单的
s/old/new/
。对于任何更复杂的问题,您应该使用
awk
,具体来说是GNU awk,您可以从Arnold Robbins的《有效的awk编程》一书中学习到这一点。
$ awk -f tst.awk file
> stat = Sent
> relay = mx.company.example.com.
> xdelay = 00:00:01
> to = user1@company.example.com
> dsn = 2.0.0
> mailer = esmtp
> delay = 00:00:02
> pri = 193069
-----
-----
> from = user1@dont-cross-the-memes.example.com
> relay = proton.dont-cross-the-memes.example.com
> nrcpts = 1
> class = -30
> size = 38065260
> proto = ESMTP
> msgid = gnDSaYSEaP4Yk/.F0EhYbIYcihGO8Vd.dont-cross-the-memes.example.com
> daemon = MTA-v6
-----
Jan 16 08:33:06 user1@dont-cross-the-memes.example.com