2

This is sample of network interface configuration in Cisco IOS. Let's name it as cisco.txt.

!
interface FastEthernet0/1
 shutdown
!
interface FastEthernet0/2
 switchport access vlan 20
!
interface FastEthernet0/3
 switchport mode access
!
interface FastEthernet0/4
!
interface FastEthernet0/5
 switchport access vlan 50
 switchport mode access
!

What I want to do is to grep the interfaces that do not have the following keyword:

shutdown|switchport access vlan \d+|switchport mode access

However, I do not really know how to do this at the moment. The only thing I can think now is to grep those matches the pattern like this.

grep -P 'interface|shutdown|switchport access vlan \d+|switchport mode access' cisco.txt

E.g.

$ grep -P 'interface|shutdown|switchport access vlan \d+|switchport mode access' cisco.txt
interface FastEthernet0/1
 shutdown
interface FastEthernet0/2
 switchport access vlan 20
interface FastEthernet0/3
 switchport mode access
interface FastEthernet0/4
interface FastEthernet0/5
 switchport access vlan 50
 switchport mode access
$ 

I've also tried -v, --invert-match to select non-matching lines, but the only output that I've got is this.

$ grep -vP 'interface|shutdown|switchport access vlan \d+|switchport mode access' cisco.txt
!
!
!
!
!
!
$ 

I was hoping to get the following output only based on my critera above.

interface FastEthernet0/4

Also, if grep is not the proper tool for this, please let me know the alternative.

Update

Thanks @AdminBee, it works with previous example. However, when I try it with different config, I do not get similar result.

I've changed the criteria on awk script a little bit.

awk 'BEGIN{RS="!\n";FS=OFS="\n"} {for (i=i;i<=NF;i++) {if ($i~/^ *(switchport mode trunk|switchport mode access|switchport access vlan ) *$/) next}} NF' cisco2.txt

If any of these criteria found, then do not print the interface which so it would only print the interface GigabitEthernet 1/3

switchport mode trunk|switchport mode access|switchport access vlan

new config file

$ cat cisco2.txt 
hostname ExampleSwitch

interface GigabitEthernet 1/1
 switchport mode trunk
 shutdown

interface GigabitEthernet 1/2
 switchport mode access
 switchport access vlan 20
 switchport nonegotiate
 no cdp enable

interface GigabitEthernet 1/3
 no switchport
 ip address 192.0.2.1 255.255.255.0
$ 

Output ( nothing is displayed )

$ awk 'BEGIN{RS="!\n";FS=OFS="\n"} {for (i=i;i<=NF;i++) {if ($i~/^ *(switchport mode trunk|switchport mode access|switchport access vlan ) *$/) next}} NF' cisco2.txt
$ 

Desired output

interface GigabitEthernet 1/3

or

interface GigabitEthernet 1/3
 no switchport
 ip address 192.0.2.1 255.255.255.0
2

You could use awk for the purpose:

awk 'BEGIN{RS="!\n";FS=OFS="\n"}
     {for (i=i;i<=NF;i++) {if ($i~/^ *(shutdown|switchport access vlan [[:digit:]]+|switchport mode access) *$/) next}}
     NF' cisco.txt

This will treat lines with ! as record separator and read the entire "paragraph" associated with one interface at a time. The record will be split into "fields" linewise i.e. one line is interpreted as one "field".

The program will then iterate over all fields, and if either of your patterns is found, skip execution to the next record. If none of the keywords are found, and there is at least one line in the paragraph (NF is non-zero; this is to prevent output of empty records), the paragraph is printed. For your example:

user@host~$ awk 'BEGIN{RS="!\n";FS=OFS="\n"} {for (i=i;i<=NF;i++) {if ($i~/^ *(shutdown|switchport access vlan [[:digit:]]+|switchport mode access) *$/) next}} NF' cisco.txt
interface FastEthernet0/4

If you only want to ensure that you only print the line containing the interface statement, modify the NF to

NF {print $1}

or even more selective

NF && $1~/interface/ {print $1}

Update

The second example you posted in your update uses a different file format (the delimiter is changed now, and there can be secions other than interface), hence the solution proposed above doesn't work there. Instead, try the following:

awk 'BEGIN{RS="";FS=OFS="\n"}
     {for (i=i;i<=NF;i++) {if ($i~/^ *(switchport mode trunk|switchport mode access|switchport access vlan ) *$/) next}}
     NF && $1~/interface/ {print $1}' cisco2.txt

This sets the record separator to an empty line, but otherwise works the same as above. However, output is only produced if the section starts with interface (to exclude the hostname line e.g.), and will (again) print only the first line containing the interface statement.

3
  • Thanks @AdminBee, it works with previous example. However, when I try it with different config, I do not get similar result. – user11392987 Jan 6 at 16:45
  • 1
    @user11392987 your different config doesn't match the pattern/shape you've asked us about, because each section is no longer delimited with ! – roaima Jan 6 at 17:35
  • @user11392987 I have updated the answer to reflect your second config example. Please note however that if you have other follow-up questions, you are requested to post them as new questions, and not edit the existing question. Also, if you found the answer useful, please consider accepting it so that others facing a similar issue may find it more easily. – AdminBee Jan 7 at 8:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.