1

The following command has the following output:

[xr-vm_node0_RP0_CPU0:~]$show_snmp_interface_notif -x .*
ifName : Null0                 ifIndex: 1
ifName : MgmtEth0/RP0/CPU0/0   ifIndex: 2
ifName : Loopback0             ifIndex: 5
ifName : Bundle-Ether25        ifIndex: 6
ifName : Bundle-Ether42        ifIndex: 7
ifName : Optics0/0/0/0         ifIndex: 8
ifName : Optics0/0/0/1         ifIndex: 9
...
ifName : HundredGigE0/0/1/3    ifIndex: 92
ifName : HundredGigE0/0/1/2    ifIndex: 93
ifName : HundredGigE0/0/1/1    ifIndex: 94
ifName : HundredGigE0/0/1/0    ifIndex: 95
ifName : Loopback1             ifIndex: 96

I would like to extract the lines where the last column equals any of the numbers below.

2  6  7  52  53  54  55  56  57  89  90  91

Attempts: 1) Confirmed that above elements were stored and printed via array[i] correctly

[xr-vm_node0_RP0_CPU0:~]$show_snmp_interface_notif -x .* | awk 'BEGIN{split("2  6  7  52  53  54  55  56  57  89  90  91",array)}; END {for (i in array) print array[i]}'
2
6
7
52
53
54
55
56
57
89
90
91

2) Verified that $NF matches the last column

[xr-vm_node0_RP0_CPU0:~]$show_snmp_interface_notif -x .* | awk '{print $NF}'
1
2
5
6
7
8
9
10
11
12
...
92
93
94
95
96

3) Wrote the following awk statement which does not print anything. I suspect the print statement is incorrect. We need to pull out the complete line if the last column matches any of the specified elements in array[i].

[xr-vm_node0_RP0_CPU0:~]$show_snmp_interface_notif -x .* | awk 'BEGIN{split("2  6  7  52  53  54  55  56  57  89  90  91",array)}; END {for (i in array); if(array[i]==$NF) { print $i }}'

[xr-vm_node0_RP0_CPU0:~]$show_snmp_interface_notif -x .* | awk 'BEGIN{split("2  6  7  52  53  54  55  56  57  89  90  91",array)}; END {for (i in array); if(array[i]==$NF) { print i }}'

4 Answers 4

3

Could you please try following.

awk '
BEGIN{
  num=split("2 6 7 52 53 54 55 56 57 89 90 91",array," ")
  for(i=1;i<=num;i++){
    b[array[i]]
  }
}
($NF in b)
'   Input_file

OR

your_command | awk '
BEGIN{
  num=split("2 6 7 52 53 54 55 56 57 89 90 91",array," ")
  for(i=1;i<=num;i++){
    b[array[i]]
  }
}
($NF in b)' 
Sign up to request clarification or add additional context in comments.

1 Comment

@user Didn't need to test. Time for one array lookup < for looping all choises or regex.
2

Remove one ; and END to run for loop with every row of stdin. With ; your for loop has no body.

... | awk 'BEGIN{split("2  6  7  52  53  54  55  56  57  89  90  91",array)}; {for (i in array) if(array[i]==$NF) { print }}'

Output:

ifName : MgmtEth0/RP0/CPU0/0   ifIndex: 2
ifName : Bundle-Ether25        ifIndex: 6
ifName : Bundle-Ether42        ifIndex: 7

Comments

2

This can be done without array. (If data comes for another source array my be fine to use). Should be faster since no loop are involved.

your commands | awk '$NF~/^(2|6|7|52|53|54|55|56|57|89|90|92)$/'
ifName : MgmtEth0/RP0/CPU0/0   ifIndex: 2
ifName : Bundle-Ether25        ifIndex: 6
ifName : Bundle-Ether42        ifIndex: 7

1 Comment

@user Normally loops are slower, so If I can avoid it, I do, but depending of the amount of data this can vary. Anyway this is less complicated and easier to understand.
0

there's no need to pre-hard-code anything : say if you have a dynamic list of values you wanna include, place them at shell variable ${__} :

    __=''
    for __ in ' 2 8 6  7  52  53  54  55  56  57  89  90  91 ' \
              ' 1 5  9  92 96 ' ; do
       export __
       echo "${input_data}" | mawk "$( mawk -v __="${__}" 'BEGIN {

          printf("%.*sBEGIN { printf(\"\\n\\t [ %s ]\\n" \
                 "\\n\") >> (\"/dev/stderr\") }  /: (%s)$/",
                ($+(OFS = "|") = __)*_, NF = NF, $-_, $-_) }' )" | gcat -b
    done
input
ifName : Null0                 ifIndex: 1
ifName : MgmtEth0/RP0/CPU0/0   ifIndex: 2
ifName : Loopback0             ifIndex: 5
ifName : Bundle-Ether25        ifIndex: 6
ifName : Bundle-Ether42        ifIndex: 7
ifName : Optics0/0/0/0         ifIndex: 8
ifName : Optics0/0/0/1         ifIndex: 9
...
ifName : HundredGigE0/0/1/3    ifIndex: 92
ifName : HundredGigE0/0/1/2    ifIndex: 93
ifName : HundredGigE0/0/1/1    ifIndex: 94
ifName : HundredGigE0/0/1/0    ifIndex: 95
ifName : Loopback1             ifIndex: 96
output
 [ 2|8|6|7|52|53|54|55|56|57|89|90|91 ]

 1  ifName : MgmtEth0/RP0/CPU0/0   ifIndex: 2
 2  ifName : Bundle-Ether25        ifIndex: 6
 3  ifName : Bundle-Ether42        ifIndex: 7
 4  ifName : Optics0/0/0/0         ifIndex: 8

 [ 1|5|9|92|96 ]

 1  ifName : Null0                 ifIndex: 1
 2  ifName : Loopback0             ifIndex: 5
 3  ifName : Optics0/0/0/1         ifIndex: 9
 4  ifName : HundredGigE0/0/1/3    ifIndex: 92
 5  ifName : Loopback1             ifIndex: 96

once you turn on the gawk profiler, you can see how a single nested-subshell does wonders :

BEGIN { printf("\n\t [ 2|8|6|7|52|53|54|55|56|57|89|90|91 ]\n\n")
                                           >> ("/dev/stderr")

} /: (2|8|6|7|52|53|54|55|56|57|89|90|91)$/

BEGIN { printf("\n\t [ 1|5|9|92|96 ]\n\n") >> ("/dev/stderr")

}  /: (1|5|9|92|96)$/

especially for larger inputs, the time spent dynamically generating the code pays itself off multiple times over from speed gains via the newly-hard-coded regex/constants, thus avoiding any arrays or loops, while still being able to parameterize input

code itself has been tested on mawk gawk and nawk, and it should in theory also work with busybox awk

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.