0

Input 1

eno16780032: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.0.1 netmask 255.255.255.255  broadcast 192.168.0.254
    ether 00:50:56:00:00:00  txqueuelen 1000  (Ethernet)
eno33559296: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.0.2  netmask 255.255.255.255  broadcast 192.168.0.254
    ether 00:50:56:00:00:01  txqueuelen 1000  (Ethernet)
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
    inet 127.0.0.1  netmask 255.0.0.0
    loop  txqueuelen 0  (Local Loopback)

Input 2

bond0   Link encap:Ethernet  HWaddr 00:50:56:00:00:00
        inet addr:192.168.0.1   Bcast:192.168.0.254  Mask:255.255.254.255
        UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
bond0:0 Link encap:Ethernet  HWaddr 00:50:56:00:00:00
        inet addr:192.168.0.1  Bcast:192.168.0.254  Mask:255.255.254.255
        UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
eth0    Link encap:Ethernet  HWaddr 00:50:56:00:00:00
        UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
eth1    Link encap:Ethernet  HWaddr 00:50:56:00:00:00
        UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
lo      Link encap:Local Loopback
        inet addr:127.0.0.1  Mask:255.0.0.0
        UP LOOPBACK RUNNING  MTU:65536  Metric:1

I want output as like, ( Basically to extract Interface, IP and Hardware Address )

Output1

eno16780032 192.168.0.1 00:50:56:00:00:00 
eno33559296 192.168.0.2 00:50:56:00:00:01   
lo          127.0.0.1

Output2

bond0   192.168.0.1 00:50:56:00:00:00
bond0:0 192.168.0.2 00:50:56:00:00:00
eth0                00:50:56:00:00:00 ===> No IP since its under bonding
eth1                00:50:56:00:00:00 ===> No IP since its under bonding
lo      127.0.0.1

I've tried with awk (awk '/flags|Link/{a=$1;hw=$NF;next;} /inet /{ip=$2;print a,ip,hw}'), but since Not all match pattern available on each line Unable to get the desired ouput.

So thinking to add matching pattern empty "inet addr:" on input 2 file for the interfaces are part of bonding and the things would be fine.

  1. Can you please help either to add empty "inet addr:" after interface line

     eth0    Link encap:Ethernet  HWaddr 00:50:56:00:00:00
             UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
             inet addr:   <==== Insert empty line
    

or

  1. To get the desired output as mentioned above.
2
  • By the way, Your Input2 has two mistakes: bond0:0 is an address (not an interface) for the same reasons it's explained that ifconfig is legacy, and thus can't receive the same address as bond0, including with the ifconfig command. Likewise the netmask 255.255.254.255 is invalid.
    – A.B
    May 31, 2021 at 13:54
  • These all manipulated data, since I do not be too expressive of my own IP addresses 😆😆
    – skmohan
    May 31, 2021 at 14:13

3 Answers 3

2
awk 'BEGIN { OFS="\t" }; # use tab for output separator

     ! /^ / {   # line doesnt begin with a space, must be an interface line, extract it
       i=gensub(/:$/,"",1,$1)
       mac[i]=$5;     # this will either be a HWAddr or empty
       ifaces[i]=1
     };

     /^ +inet/ { ip[i] = ip[i] " " gensub(/addr:/,"",1,$2) };

     /^ +ether/ { mac[i]=$2};  # this will only match if there WASNT a HWAddr on the iface line

     END {
       for (i in ifaces) {
         sub(/^ +/,"",ip[i]); # remove unwanted space from beginning of ip addresses
         #if (ip[i]  == "") ip[i]  = "--"; #optional
         #if (mac[i] == "") mac[i] = "--"; #optional
         print i, ip[i], mac[i]
       }
     }' filename | sort

(or just pipe ifconfig into it rather than give it an input filename)

This awk script can handle either variant of ifconfig output, and outputs three tab-separated fields: interface names, IP addresses, and MAC addresses.

If there are more than one IP addresses in the second field, they are separated by a space.

Output when run against input1 and piped into sort:

eno16780032     192.168.0.1     00:50:56:00:00:00
eno33559296     192.168.0.2     00:50:56:00:00:01
lo      127.0.0.1

Output when run against input2 and piped into sort:

bond0:0 192.168.0.1     00:50:56:00:00:00
bond0   192.168.0.1     00:50:56:00:00:00
eth0            00:50:56:00:00:00
eth1            00:50:56:00:00:00
lo      127.0.0.1

NOTE: your requested output had 192.168.0.2 as the IP address for bond0:0, but your sample data had 192.168.0.1, same as for the bond0 interface.

If you uncomment the "optional" lines in the script, it will ensure that there will always be 3 tab-separated output fields, even if the IP address or MAC address field is empty.

Output would look like:

eno16780032     192.168.0.1     00:50:56:00:00:00
eno33559296     192.168.0.2     00:50:56:00:00:01
lo      127.0.0.1       --

and

bond0:0 192.168.0.1     00:50:56:00:00:00
bond0   192.168.0.1     00:50:56:00:00:00
eth0    --      00:50:56:00:00:00
eth1    --      00:50:56:00:00:00
lo      127.0.0.1       --

Additional comments:

It is a mistake to ignore the ip command. It has been standard on Linux for years now, and many programs that add secondary/alternate/"alias" IP addresses to an interface will use it. Secondary IP addresses added to an interface in this manner will ONLY be displayed with ip addr show, they will NOT show up when ifconfig is run.

ifconfig should be regarded as legacy only, at least on Linux.

1
  • Thanks cas… indeed ifconfig is very legacy but I’ve requirement to use it.. not best option though
    – skmohan
    May 31, 2021 at 13:48
2

A naive but effective solution is to read the output of ifconfig in reverse; this way, every time we come across the first line of a block, either we have found the fields we are interested in or we can safely assume they are missing. Given the AWK script:

{
  for (i = 1; i  <= NF; i++) {
    if ($i == "inet") {
      ip = $(i+1)
      sub(/.*:/, "", ip)
    }
    if ($i == "HWaddr" || $i == "ether")
      hw = $(i+1)
  }
}
/^[^[:blank:]]/ {
  nm = $1
  sub(/:$/, "", nm)
  print nm,ip,hw
  nm = ""
  ip = ""
  hw = ""
}

and assuming you saved it as awkscript, you may then do:

ifconfig | tac | awk -f awkscript | tac | column -s ' ' -t

In case the non-standard tac command was not available to you, this AWK script could be easily modified to save the whole input stream in an array and process it in reverse in an END block.

1
  • Thanks, it was helpful. Luckily have tac command and it works fine. Will explore more and will let u know..
    – skmohan
    May 31, 2021 at 13:45
1
$ cat tst.awk
!/^[[:space:]]/ { if (NR>1) prt() }
{ rec = rec FS $0 }
END { prt() }

function prt(   flds,i,nf,map) {
    sub(/: /," ",rec)
    sub(/ ether /," HWaddr ",rec)
    sub(/ inet addr:/," inet ",rec)

    nf = split(rec,flds)
    map["iface"] = flds[1]
    for (i=2; i<nf; i++) {
        map[flds[i]] = flds[i+1]
    }
    print map["iface"], map["inet"], map["HWaddr"]

    rec = ""
}

$ awk -f tst.awk file1 | column -s' ' -t
eno16780032  192.168.0.1  00:50:56:00:00:00
eno33559296  192.168.0.2  00:50:56:00:00:01
lo           127.0.0.1

$ awk -f tst.awk file2 | column -s' ' -t
bond0    192.168.0.1  00:50:56:00:00:00
bond0:0  192.168.0.1  00:50:56:00:00:00
eth0                  00:50:56:00:00:00
eth1                  00:50:56:00:00:00
lo       127.0.0.1

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.