1

我想将 grep 与 -f、-i 和 -v 选项一起使用。我有一个包含以下内容的模式文件:

vchkpw-pop3 vchkpw-
提交
user_unknown
unknown_user
address_rejected
no_such_user
does_not_exist
invalid_recipient
mailbox_unavailable
user_not_found
no_mailbox_here

当我处理我的 qmail 邮件日志文件时,我想排除上述所有条款。

使用 Grep 2.5.1,它似乎不适用于从第 3 个位置开始的任何模式。

我正在使用一行 bash 代码来解析我的邮件日志文件。请参阅下面的行:

cat /var/log/maillog | tai64n2tai | awk '{$1="";$2="";$3="";$4="";$5="";print}'
| grep -v vchkpw-pop3 | grep -v vchkpw-submission | awk '{sub(/^[ \t]+/,"")};1'
| qlogselect start $STARTDAY end $ENDDAY | matchup > $QMAILSTATS 5>/dev/null

而不是在管道中使用多个 grep -v "sometext" ,我想在它们的位置使用 grep -vif patterns.txt 。

但是,我的问题是,在我的 grep 版本中,如果模式中包含下划线 (_),则不允许我同时使用 f 和 i 选项。如果我删除下划线,那么模式会按预期匹配。

这是我在解析邮件日志时要省略的示例行:

Sep 20 15:46:50 m qmail: 1348123610.323831 delivery 11150428: failure: 204.119.19.51_does_not_like_recipient./Remote_host_said:_550_5.1.1_User_unknown/Giving_up_on_204.119.19.51./ 

由于错误消息取决于我正在联系的邮件服务器,因此模式 user_unknown 有时有大写字母,有时没有。

有人有更好的解决方案吗?

我喜欢不必每次都编辑一行 bash 命令,而只需从文件中添加/删除模式的想法。

4

1 回答 1

0

这是使用 的一种方法GNU awk,假设您将模式保存在名为patterns.txt. 这是的内容script.awk

BEGIN {
    IGNORECASE=1
}

FNR==NR {
    patterns[$0]++
    counter++
    next
}

{
    $1=$2=$3=$4=$5=""
    sub(/^[ \t]+/,"")

    for (i in patterns) {
        if ($0 !~ i) {
            count++
        }
    }

    if (counter == count \
        && !/^$/) {
            print
    }

    count = 0
}

像这样运行:

< /var/log/maillog | tai64n2tai | awk -f script.awk patterns.txt - | qlogselect start $STARTDAY end $ENDDAY | matchup > $QMAILSTATS 5>/dev/null

或者,如果您不想使用脚本,您会发现这一行很有用:

< /var/log/maillog | tai64n2tai | awk 'BEGIN { IGNORECASE=1 } FNR==NR { patterns[$0]++; counter++; next } { $1=$2=$3=$4=$5=""; sub(/^[ \t]+/,""); for (i in patterns) { if ($0 !~ i) { count++ } } if (counter == count && !/^$/) { print } count = 0 }' patterns.txt - | qlogselect start $STARTDAY end $ENDDAY | matchup > $QMAILSTATS 5>/dev/null
于 2012-09-20T14:11:27.060 回答