How to format ifconfig output

I need to translate the result of the ifconfig -a command to the following format

 IFACE eth0 192.168.30.8 Ethernet IFACE eth1 212.233.112.171 Ethernet IFACE lo 127.0.0.1 Local Loopback IFACE pan0 0.0.0.0 Ethernet IFACE tunl0 0.0.0.0 IPIP Tunnel 

I know that I should do this with sed or something similar. At the moment, I have the following "script":

 ifconfig -a | sed -r -n -e 'N' -e 's/(\w+)(\s*)(Link\sencap:)(\w+(\s\w+)*)([^\n]*)\n\s+(inet\saddr:)([0-9]{1,3}(\.[0-9]{1,3}){3}).*/IFACE \1 \8 \4/p' 

The original output of ifconfig -a is ( ... means the omitted parts)

 eth0 Link encap:Ethernet HWaddr f4:ce:46:99:22:57 inet addr:192.168.30.8 Bcast:192.168.31.255 Mask:255.255.254.0 ... eth1 Link encap:Ethernet HWaddr 00:23:7d:fd:a2:d0 inet addr:212.233.112.171 Bcast:212.233.112.175 Mask:255.255.255.240 ... lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 ... pan0 Link encap:Ethernet HWaddr f6:d0:8a:0e:7b:95 BROADCAST MULTICAST MTU:1500 Metric:1 ... tunl0 Link encap:IPIP Tunnel HWaddr NOARP MTU:1480 Metric:1 ... 

The first problem with this conversion is that the IP address is on the second line of the name and type of interface. A used the -N argument for concat lines, but they are concat pairs, and if the interface name is on an odd line, I have problems: the script skips the interface on an odd line like this (Note that there is no mention of pan0 in the output. ):

 IFACE eth0 192.168.30.8 Ethernet IFACE eth1 212.233.112.171 Ethernet IFACE lo 127.0.0.1 Local Loopback IFACE tunl0 IPIP Tunnel 

The second problem is that I do not know how to insert a null address if ifconfig -a does not have an IP address.

+4
source share
4 answers

Note that ifconfig output is platform dependent, so this is not a very portable way to do this.

Regarding the sed solution, I think you need to break the parsing into several stages, something like this should work (GNU sed):

parse.sed

 s/^([^ ]+) */\1\n/ # interface name s/Link encap:(.*)( |$).*/\1/ # link encapsulation N # append next line to PS /inet addr/! s/\n[^\n]*$/\n0.0.0.0\n/ # use 0.0.0.0 if no "inet addr" s/ *inet addr:([^ ]+).*/\1\n/ # capture ip address if present s/\n[^\n]*$// # cleanup the last line s/([^\n]+)\n([^\n]+)\n([^\n]+)/IFACE \1 \3 \2/p # print entry s/.*// # empty PS : loop # \ N # \ /^\n$/b # skip until next empty line s/.*// # / b loop # / 

Explanation

The idea is to capture all the relevant information in the template space using line separators.

Testing

Follow these steps:

 ifconfig -a | sed -rf parse.sed 

Output:

 IFACE eth0 192.168.30.8 Ethernet IFACE eth1 212.233.112.171 Ethernet IFACE lo 127.0.0.1 Local Loopback IFACE pan0 0.0.0.0 Ethernet IFACE tunl0 IPIP Tunnel 
+4
source

I have something!

 ifconfig -a | tr -s ' ' | awk -F'[: ]' ' {if (/^[az]/) printf "IFACE " $1 " " $4} {if (/inet addr:/) print " " $4}' 

Explanation:

  • tr -s ' ' remove multiple spaces.
  • -F'[: ]' defines several delimiters : and (space).
  • {if (/^[az]/) ... when something starts with a letter, type field 1 and 4.
  • {if (/inet addr:/) ... whenever something contains _inet addr_ , the print field is $ 4

Output:

 IFACE lo Local127.0.0.1 IFACE wlan0 Ethernet192.168.1.61 

As you can see, they are not in the same order, but I could not get it.

+1
source

I already accepted Thor's answer, but here is my solution, which is a little different. I thought about it, waiting for an answer.

 ip addr | sed -r ':a;N;$!ba;s/\n\s/ /g' | sed -r -n -e 's/^([0-9]+):\s(\w+).*(link\/(\w+))\s[a-f0-9:.]{,17}\sbrd\s[a-f0-9:.]{,17}\s*(inet\s([0-9]{1,3}(\.[0-9]{1,3}){3})).*/IFACE \2 \6 \4/p' -e 's/^([0-9]+):\s(\w+).*(link\/(\w+))\s[a-f0-9:.]{,17}\sbrd\s[a-f0-9:.]{,17}.*/IFACE \2 0.0.0.0 \4/p' 

output:

 IFACE lo 127.0.0.1 loopback IFACE eth0 192.168.30.8 ether IFACE eth1 212.233.112.171 ether IFACE pan0 0.0.0.0 ether IFACE tunl0 0.0.0.0 ipip 

The main advantage - it can be called as is. The second advantage is that the order of the interfaces is aligned with the index of the interface (I got this when I started comparing the results of ifconfig and ip addr ).

But the Thorn solution is much readable and supported.

0
source

For greater readability and ease of maintenance, you can use awk for this. Here is one way with GNU awk:

parse.awk

 function get2(s) { split(s, a, ":") return a[2] } { link = ip = "" for(i=2; i<=NF; i++) { switch($i) { case /Link encap/ : link = get2($i); break case /inet addr/ : ip = get2($i); break } } print "IFACE", $1, (ip=="")?"0.0.0.0":ip, link } 

Run it as follows:

 ifconfig -a | awk -f parse.awk RS='\n\n' FS=' {2,}|\n' 

Output:

 IFACE eth0 192.168.30.8 Ethernet IFACE eth1 212.233.112.171 Ethernet IFACE lo 127.0.0.1 Local Loopback IFACE pan0 0.0.0.0 Ethernet IFACE tunl0 0.0.0.0 IPIP Tunnel 
0
source

All Articles