views:

569

answers:

4

I have a file containing the string

ipAddress=10.78.90.137;10.78.90.149

I'd like to place these two IP addresses in a bash array. To achieve that I tried the following:

n=$(grep -i ipaddress /opt/ipfile |  cut -d'=' -f2 | tr ';' ' ')

This results in extracting the values alright but for some reason the size of the array is returned as 1 and I notice that both the values are identified as the first element in the array. That is

echo ${n[0]}

returns

10.78.90.137 10.78.90.149

How do I fix this?

Thanks for the help!

+1  A: 

This one works:

n=(`grep -i ipaddress filename | cut -d"=" -f2 | tr ';' ' '`)

EDIT: (improved, nestable version as per Dennis)

n=($(grep -i ipaddress filename | cut -d"=" -f2 | tr ';' ' '))
Joy Dutta
If you change your backticks to `$()` I'll upvote you.
Dennis Williamson
This does not work. BTW, isn't the expression same as the one I'm using? Is there any difference between using $() and ` (backticks)?
calvinkrishy
It works for me. This is what it would look like with `$()`: `n=($(grep -i ipaddress filename | cut -d"=" -f2 | tr ';' ' '))` - the outer parentheses make it into an array. It's better to use `$()` because they can be nested and it's easier to get quoting and escaping right and they're more readable: http://mywiki.wooledge.org/BashFAQ/082
Dennis Williamson
Thanks Dennis, the non-backtick version is definitely better.
Joy Dutta
+6  A: 

do you really need an array

bash

$ ipAddress="10.78.90.137;10.78.90.149"
$ IFS=";"
$ set -- $ipAddress
$ echo $1
10.78.90.137
$ echo $2
10.78.90.149
$ unset IFS
$ echo $@ #this is "array"

if you want to put into array

$ a=( $@ )
$ echo ${a[0]}
10.78.90.137
$ echo ${a[1]}
10.78.90.149

@OP, regarding your method: set your IFS to a space

$ IFS=" "
$ n=( $(grep -i ipaddress file |  cut -d'=' -f2 | tr ';' ' ' | sed 's/"//g' ) )
$ echo ${n[1]}
10.78.90.149
$ echo ${n[0]}
10.78.90.137
$ unset IFS

Also, there is no need to use so many tools. you can just use awk, or simply the bash shell

#!/bin/bash
declare -a arr
while IFS="=" read -r caption addresses
do
 case "$caption" in 
    ipAddress*)
        addresses=${addresses//[\"]/}
        arr=( ${arr[@]} ${addresses//;/ } )
 esac
done < "file"
echo ${arr[@]}

output

$ more file
foo
bar
ipAddress="10.78.91.138;10.78.90.150;10.77.1.101"
foo1
ipAddress="10.78.90.137;10.78.90.149"
bar1

$./shell.sh
10.78.91.138 10.78.90.150 10.77.1.101 10.78.90.137 10.78.90.149

gawk

$ n=( $(gawk -F"=" '/ipAddress/{gsub(/\"/,"",$2);gsub(/;/," ",$2) ;printf $2" "}' file) )
$ echo ${n[@]}
10.78.91.138 10.78.90.150 10.77.1.101 10.78.90.137 10.78.90.149
ghostdog74
The values are used later in the script. If they are stored in an array it would make it easier to iterate and perform other operations on them, hence the need to store them in an array. The method you describe should help me. Thanks!Could you please share your thoughts on why the method I'm using is failing?
calvinkrishy
see my edit. one way is to set IFS.
ghostdog74
Thanks. Learnt a few new tricks today!
calvinkrishy
A: 

A variation on a theme:

$ line=$(grep -i ipaddress /opt/ipfile)
$ saveIFS="$IFS"    # always save it and put it back to be safe
$ IFS="=;"
$ n=($line)
$ IFS="$saveIFS"
$ echo ${n[0]}
ipAddress
$ echo ${n[1]}
10.78.90.137
$ echo ${n[2]}
10.78.90.149

If the file has no other contents, you may not need the grep and you could read in the whole file.

$ saveIFS="$IFS"
$ IFS="=;"
$ n=$(</opt/ipfile)
$ IFS="$saveIFS"
Dennis Williamson
A: 

A Perl solution:

n=($(perl -ne 's/ipAddress=(.*);/$1 / && print' filename))

which tests for and removes the unwanted characters in one operation.

J. A. Faucett