Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Explanation:

I have a small bash script which simply runs any Linux command (e.g. say ifconfig)

The typical output of ifconfig is something like this:

eth0      Link encap:Ethernet  HWaddr 30:F7:0D:6D:34:CA
          inet addr:10.106.145.12  Bcast:10.106.145.255  Mask:255.255.255.0
          inet6 addr: fe80::32f7:dff:fe6d:34ca/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1104666 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2171 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:444437904 (423.8 MiB)  TX bytes:238380 (232.7 KiB)

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.255.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:15900 errors:0 dropped:0 overruns:0 frame:0
          TX packets:15900 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:467306 (456.3 KiB)  TX bytes:467306 (456.3 KiB)

Now what most people usually do is store the entire output into a file/variable and parse based on that. I however want to know if there is anyway that I could put specific parts of the output in more than one variable (say a bash variable called ${IPETH0} to carry the IP address 10.106.145.12 from eth0 and ${IPLO} to carry the IP address 127.0.0.1 from lo in the above example without running ifconfig command twice).

Something like what tee command does with the input but I want to do this for the output and store the output into 2 or more variables in one go. Any ideas?

share|improve this question
1  
See this Q&A: unix.stackexchange.com/questions/87468/… –  slm Aug 26 '13 at 18:19
    
@slm: I am not trying to obtain the IP address. I wanna know how I can store broken-down output of a command into more than one bash variable. The example you pointed out still stores output in a single variable. –  Arpith Aug 26 '13 at 18:22
    
@choroba - read can –  jordanm Aug 26 '13 at 18:55
    
@Arpith - yeah that was just to get you started, not show you exactly your solution. –  slm Aug 26 '13 at 20:59

4 Answers 4

Got the answer:

$ read IPETH0 IPLO <<< $(ifconfig | awk '/inet[[:space:]]/ { print $2 }' | cut -d ':' -f 2)
$ echo "${IPETH0}"
192.168.23.2
$ echo "${IPLO}"
127.0.0.1

This assumes the order of the eth0 and lo interfaces, but it shows the basic idea.

Pure awk

You can do this exclusively in awk using the split function:

$ read IPETH0 IPLO <<< $(ifconfig | awk '/inet[[:space:]]/ { split($2,a,":"); print a[2]}')
share|improve this answer
    
You shouldn't use awk and cut together. You only need awk. –  jordanm Aug 26 '13 at 18:54
    
I know. I know very minimal awk. Hence the cacophony. :-p –  Arpith Aug 26 '13 at 18:57
2  
@jordanm - i added a awk only method. –  slm Aug 27 '13 at 0:20

I presume that you know for each of your commands which part of the command's return you want to store.

In your example this would be words number 7 and 47.

Do it like this (note the back ticks around your command ifconfig):

array=(`ifconfig`)

Show all elements of this array:

echo ${array[@]}
eth0 Link encap:Ethernet HWaddr 30:F7:0D:6D:34:CA inet addr:10.106.145.12 Bcast:10.106.145.255 Mask:255.255.255.0 inet6 addr: fe80::32f7:dff:fe6d:34ca/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1104666 errors:0 dropped:0 overruns:0 frame:0 TX packets:2171 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:444437904 (423.8 MiB) TX bytes:238380 (232.7 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.255.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:15900 errors:0 dropped:0 overruns:0 frame:0 TX packets:15900 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:467306 (456.3 KiB) TX bytes:467306 (456.3 KiB)

Show specific words:

echo ${array[6]} ${array[46]}
addr:10.106.145.12 addr:127.0.0.1

Pipe the result into sed to extract only your IP addresses:

echo ${array[6]} ${array[46]} | sed 's/addr://g'
10.106.145.12 127.0.0.1

Using Arpith's nifty approach with 'read' here is the flexible answer.

read IPETH0 IPLO <<< $(echo ${array[6]} ${array[46]} |\
sed 's/addr://g')
echo $IPETH0 $IPLO
10.106.145.12 127.0.0.1

Please note that array elements are being counted from 0. Therefore your word number 7 would be referred to as "${array[6]}".

The array indexes are positive integers. So you can do all sorts of calculations in your shell script to pick specific words (like ranges or for-loops) ...

To write a portable script you would need to keep a kind of table with these numbers. On my system (BSD) the IP addresses would be numbers 17 and 49 instead of your Linux numbers 7 and 47. Also the resulting strings look different (disregarding my local and Arpith's global ID address):

echo ${array2[16]}
192.168.0.103

echo ${array2[48]}
127.0.0.1

slm's "pure awk" approach (see below) would fail on my BSD system. The split function into an array would not work as my 'ifconfig' command prints "127.0.0.1" and Arpith's "addr:127.0.0.1"...

read IPETH0 IPLO <<< $(ifconfig |\
 awk '/inet[[:space:]]/ { split($2,a,":"); print a[2]}')

HTH

bernie

share|improve this answer
    
Great answer. +1 for the BSD POV. –  Arpith Aug 27 '13 at 1:09

A usual way to do that is to have for instance awk generate some bash code and have it interpreted by bash.

Like:

eval "$(
  ifconfig | awk -F '[: ]+' '
    /^[^[:blank:]]/ {iface=$1}
    /inet addr:/ {ip[iface]=$4}
    END {for (i in ip) print "IP" toupper(i) "=" ip[i]}')"
share|improve this answer

AWK :

/sbin/ifconfig | awk -F':' 'NR==2{split($2,a," "); print a[1]}'

SED :

ip -f inet addr show dev eth0 | sed -n 's/^ *inet *\([.0-9]*\).*/\1/p'

OR

ifconfig eth0 | sed -n 's/^ *inet addr:*\([.0-9]*\).*/\1/p'

GREP :

ifconfig eth0|grep -Po 't addr:\K[\d.]+'

Thanks to @Stephane Chazelas

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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