Love my blog? I'd be thankful for a gift from my geeky wishlist. Thanks!
A friend of mine recently showed me his version of extracting ip address(es) from ifconfig. The ifconfig tool on Linux is used to list IP addresses and configure network interfaces. It is sometimes necessary to capture your IP in a variable, like when writing some firewall rules.
I decided to show off and golf the extraction of IP address with four commonly used tools — Awk, sed, a version of Perl everyone has, and the latest version of Perl 5.10.
His original version was pretty ugly:
$ ifconfig | perl -ple 'print $_ if /inet addr/ and $_ =~ s/.*inet addr:((?:\d+\.){3}\d+).*/$1/g ;$_=""' | grep -v ^\s*$
My own version on my firewall was:
$ ifconfig | grep inet | awk -F: '{ print $2 }' | awk '{ print $1 }'
This looks nicer but I was uselessly using grep, and calling awk twice.
Golfing in Perl
My first attempt was to do it with grep and Perl.
$ ifconfig | grep inet | perl -ple '($_) = /addr:([^ ]+)/' 192.168.1.1 127.0.0.1
In a split second I realized that Perl does grep itself:
$ ifconfig | perl -nle '/addr:([^ ]+)/ and print $1' 192.168.1.1 127.0.0.1
Then I noticed that ‘dr:’ matches the same lines as ‘addr:’; also ‘and’ can be replaced with ‘&&’:
$ ifconfig | perl -nle '/dr:([^ ]+)/ && print $1' 192.168.1.1 127.0.0.1
The regular expression ‘([^ ]+)’ can be replaced with ‘(\S+)’, which matches non-whitespace characters:
$ ifconfig | perl -nle '/dr:(\S+)/ && print $1' 192.168.1.1 127.0.0.1
Cutting the whitespace, the final version for Perl is 37 characters long:
$ ifconfig|perl -nle'/dr:(\S+)/&&print$1' 192.168.1.1 127.0.0.1
Golfing in Perl 5.10
It can be made shorter with Perl 5.10, which introduces the new say function:
$ ifconfig|perl -nE'/dr:(\S+)/&&say$1' 192.168.1.1 127.0.0.1
The result for Perl 5.10 is 34 characters.
Golfing in sed
Then I also tried doing the same with sed:
$ ifconfig | sed -n '/dr:/{;s/.*dr://;s/ .*//;p;}'
192.168.1.1
127.0.0.1
I modified it to strip off everything that was not numbers and dots:
$ ifconfig | sed -n '/dr:/{;s/.*dr:\([0-9.]\+\) .*/\1/;p;}'
192.168.1.1
127.0.0.1
This turned out to be much longer, so I tried getting rid of backslashes, by enabling extended regexes in sed with -r argument:
$ ifconfig | sed -rn '/dr:/{;s/.*dr:([0-9.]+) .*/\1/;p;}'
192.168.1.1
127.0.0.1
I forgot that I had used the ([^ ]+) regex before. Another my friend reminded me this, shortening the sed script to:
$ ifconfig | sed -rn 's/.*r:([^ ]+) .*/\1/p' 192.168.1.1 127.0.0.1
Dropping the whitespace, sed version turned out to be 40 characters long.
Golfing in Awk
My final attempt was to optimize my original Awk version:
$ ifconfig | awk '/dr:/{gsub(/.*:/,"",$2);print$2}'
192.168.1.1
127.0.0.1
Cutting the whitespace, the Awk version is 43 characters.
The Winner
The winner in this golf tournament is Perl 5.10 with 34 chars!
Can You Do Better?
Can you golf this even shorter?
PS. my awk and sed cheat sheets might come handy!
Did you like this post? Subscribe here:
If you really enjoyed the post, I'd appreciate a gift from my geeky Amazon book wishlist. Books would make make me more educated and I would write even better posts. Thanks! :)

(5 votes, average: 4.2 out of 5)
|
|
|


September 1st, 2008 at 2:49 am
Even shows ipv6 addresses, if you have them.
ip addr sh | awk '/inet/{print$2}'September 1st, 2008 at 2:53 am
Oh dear it’s so hard to put code and text on
the same page! (It’s never done in books,
of course). I know! Let’s put all the code
into little tiny scrolling text boxes! That’ll
show em!!!!
September 1st, 2008 at 3:06 am
My first thought was the same as Uriah, though it ended up being a bit shorter anyway:
ip a | awk ‘/inet/{print $2}’
‘ip a’ is one of my most-oft-typed 4-character strings; I currently get 61 from `history | grep ip a | wc -l`.
September 1st, 2008 at 3:17 am
Uriah && Vineet Kumar, good one!
Eddie Pasternak, weeeeeee! Thanks for your feedback, that will be redesigned in the new version of catonmat!
September 1st, 2008 at 3:36 am
Umm, hello? netstat -in
September 1st, 2008 at 3:40 am
y, umm…
September 1st, 2008 at 4:17 am
& will do just as well as && in the perl version, I suspect.
September 1st, 2008 at 4:51 am
Staying with ifconfig, Ruby’s puts is one character longer than Perl 5.10’s say, but uses the very same technique, showing the similarities between both languages:
September 1st, 2008 at 6:08 am
ifconfig|grep Bcast|awk ‘ { print $2 }’|awk -F”:” ‘ { print $2 }’
September 1st, 2008 at 7:33 am
Here’s a bash/grep version:
/sbin/ifconfig | grep “inet addr” | grep -v “ddr: ” | while read a b c ; do echo $b ; done | ( IFS=’:’ ; while read a b ; do echo $b ; done )
September 1st, 2008 at 4:07 pm
This is my version…
ifconfig|egrep -o ‘dr:[^ ]+’|sed ’s/dr://g’
September 1st, 2008 at 10:48 pm
Here is the same in Scheme:
(let ([o (open-output-string)]) (parameterize ([current-output-port o]) (system “ifconfig”)) (regexp-match* #rx”(?<= inet addr:)[0-9.]*” (get-output-string o)))
September 2nd, 2008 at 5:12 pm
Here’s a Python version. We’re going for the longest one-liner, right?:
September 4th, 2008 at 11:35 am
40 characters
September 4th, 2008 at 11:41 am
Oh yeah, Nemelc! Nice one!
September 8th, 2008 at 9:16 pm
gethostip -d `hostname`
September 26th, 2008 at 5:01 pm
ifconfig | awk ‘/inet addr/{print substr($2,6)}’
September 27th, 2008 at 11:55 am
[…] 2 votesHTTP::Asyncで速度アップ - perl-mongers.org>> saved by StreetDanceTV 1 days ago1 votesGolfing the Extraction of IP Addresses from ifconfig>> saved by smpfilms 2 days ago3 votesBI Worldwide - 6th Sept 2008 - Chennai - UNIX / Windows […]
September 30th, 2008 at 5:06 am
I don’t understand the counting, so just compare the length:
That looks like 28 characters for the simple version vs 36 (not 34) for the “winner”.
September 30th, 2008 at 5:23 am
simpleton, just count the characters in the string.
ifconfig|perl -nE’/dr:(\S+)/&&say$1′ is 34 characters not 36 as you suggest. Just ‘echo -n … | wc -c’ it!
Your solution does not quite work. It does not list 127.0.0.1. Also, and IP can take 15 chars max (xxx.xxx.xxx.xxx), and you cut just 10…
September 30th, 2008 at 7:10 pm
Yep, you are right, mine won’t work because of IP address length problems.
A corrected version using grep and cut is ~45 characters.
ifconfig|grep t\ a|cut -d” ” -f12|cut -d: -f2
I still think you aren’t counting right though. Please count the characters in:
ifconfig|perl -nE’/dr:(\S+)/&&say$1′
by hand, and you will get 36.
See:
Compare:
“$1″ is getting expanded to nothing, and you lose those characters in the count.
October 22nd, 2008 at 7:08 pm
What if your system has no free entries in its process table and you are *desperately* in need of your IPv4? This can happen… in some planets.
Here’s a version for Linux without any fork()s, in the major shells that support string slicing/substrings. In some proud ~220 characters.
bash/ksh:
iface=eth0; while read Iface x x x x x x x x x x x x x SpecDst x; do [ "$Iface" = $iface ] && for i in 6 4 2 0; do echo -n $((0x${SpecDst:i:2})); ((i==0)) || echo -n .; done && echo && break; done < /proc/net/rt_cachezsh:
iface=eth0; while read Iface x x x x x x x x x x x x x SpecDst x; do [ "$Iface" = $iface ] && for i in 7 5 3 1; do echo -n $((0x${SpecDst[i,i+1]})); ((i==1)) || echo -n .; done && echo && break; done < /proc/net/rt_cacheI wonder if this is easier to read from any other place than the routing cache.
Cheers.
December 4th, 2008 at 8:37 am
Try this
ifconfig -a|grep inet|cut -d” ” -f2
December 4th, 2008 at 8:44 am
One more character less than above
ifconfig -a|grep ine|cut -d” ” -f2
December 4th, 2008 at 8:45 am
suresh, it does not work:
Even if you meant ‘:’, it does not work:
December 4th, 2008 at 8:55 am
Sorry I forget to put Double quotas
please correct it as follow
ifconfig -a|grep ine|cut -d” ” -f2
December 4th, 2008 at 9:00 am
you can also use single quota instead of double quota as quoted by Mr.Peteris
December 26th, 2008 at 11:10 am
Looks like that’s due to the differences in the output formats on different machines.
On Solaris, the following works - 33 chars:
ifconfig -a|awk ‘/inet/{print$2}’
or even the following - 32 chars:
ifconfig -a|awk ‘/ine/{print$2}’
February 8th, 2009 at 7:52 am
If you don’t mind a little extra whitespace, here’s a shorter one (I won’t even use 5.10
February 20th, 2009 at 3:17 am
It’s a little tougher to get a WAN address from a router. Here’s the best I could do:
Note the fake ip address “1.2″ as argument to traceroute.
On another distro, one could leave out the -N 1 option to traceroute, but it’s broken in Ubuntu Intrepid and won’t do fewer than 6 hops without -N 1.
March 16th, 2009 at 6:58 pm
remember GNU awk fields can be set using regex.
ifconfig | awk -F’:| *’ ‘/inet /{print $4}’
June 3rd, 2009 at 4:26 am
[…] Golfing the Extraction of IP Addresses from ifconfig […]