如何将grep尾随行的输出置于联机状态?

Modified on: Sat, 30 Jun 2018 11:39:00 +0800

假设我有这个文件:

 Thu May  8 15:32:07 2014
        User-Name = "Mark"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564

    Thu May  8 15:32:07 2014
        User-Name = "Mike"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564
    Thu May  8 15:32:07 2014
        User-Name = "Mike"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564

    Thu May  8 15:32:07 2014
        User-Name = "Mark"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564

我已设法通过grep选项使用-A获取与用户相关的信息:

grep -A4 "Mark" test
        User-Name = "Mark"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564
--
        User-Name = "Mark"
        Framed-IP-Address = 0.0.0.0
        Acct-Status-Type = Interim-Update
        Acct-Input-Octets = 95684
        Acct-Output-Octets = 23564

但是我想要的输出是这样的:

User-Name = "Mark" 
            Acct-Input-Octets = 95684 95684
            Acct-Output-Octets = 23564 23564

我们注意到我想在“Mark”之后消除前两行Framed-IP-Address = 0.0.0.0Acct-Status-Type = Interim-Update并将同一字段的所有值放在同一行中?

Warwick所示,我的问题的第一部分可以轻松回答:

grep -A4 "Mark" test| grep -v Framed-IP-Address | grep -v Acct-Status-Type

请注意,这是一个示例,该文件可能包含很多具有User-Name =“Mark”的部分,所需的输出将是这样的:

User-Name = "Mark" 
                Acct-Input-Octets = val1 val2 val3 val4 .......
                Acct-Output-Octets = val1 val2 val3 val4 ........

最佳答案

search.awk

BEGIN {
    FS = "="
    cur_username = ""
}

$1 ~ /User-Name/ {
    cur_username = $2
    gsub(/^[ \t]+/, "", cur_username)
    gsub(/[ \t]+$/, "", cur_username)
}

$1 !~ /User-Name/ {
    if ((NF != 2) || (cur_username != searched_user))
        next

    key = $1
    gsub(/^[ \t]+/, "", key)
    gsub(/[ \t]+$/, "", key)

    value = $2
    gsub(/^[ \t]+/, "", value)
        gsub(/[ \t]+$/, "", value)

    values[key] = values[key] " " value
}

END {
    printf("User-Name = %s\n", searched_user)
    for(key in values) {
        printf("\t%s =%s\n", key, values[key])
    }
}

试运行:

$ awk -f search.awk -v 'searched_user="Mark"' input 
User-Name = "Mark"
    Acct-Status-Type = Interim-Update Interim-Update
    Acct-Input-Octets = 95684 95684
    Framed-IP-Address = 0.0.0.0 0.0.0.0
    Acct-Output-Octets = 23564 23564


奖金 - group.awk用于对所有记录进行分组(太糟糕了nawk没有asorti):

BEGIN {
    FS = "="
    cur_username = ""
}

$1 ~ /User-Name/ {
    cur_username = $2
    gsub(/^[ \t]+/, "", cur_username)
    gsub(/[ \t]+$/, "", cur_username)
}

$1 !~ /User-Name/ {
    if (NF != 2)
        next

    key = $1
    gsub(/^[ \t]+/, "", key)
    gsub(/[ \t]+$/, "", key)

    value = $2
    gsub(/^[ \t]+/, "", value)
        gsub(/[ \t]+$/, "", value)

    users[cur_username,key] = users[cur_username,key] " " value
}

END {
    n = asorti(users, sorted)
    prev_username = ""
    for (i=1; i<=n; i++) {
        username_key = sorted[i]
        split(username_key, a, SUBSEP)
        username = a[1]
        key = a[2]
        value = users[sorted[i]]
        if (username != prev_username) {
            printf("User-Name = %s\n", username)
            prev_username = username
        }
        printf("\t%s =%s\n", key, value)
    }
}

试运行:

$ gawk -f group.awk input 
User-Name = "Mark"
    Acct-Input-Octets = 95684 95684
    ...
User-Name = "Mike"
    Acct-Input-Octets = 95684 95684
    ...

相关问答

添加新评论