6

i've got a bash variable that contains an IP address (no CIDR or anything, just the four octets).

i need to break that variable into four separate octets like this:

$ip = 1.2.3.4; 
$ip1 = 1
$ip2 = 2
# etc

so i can escape the period in sed. is there a better way to do this? is awk what i'm looking for?

chown
  • 51,908
  • 16
  • 134
  • 170
brent saner
  • 412
  • 1
  • 5
  • 9
  • "Escape the period in sed"? Why? What do you want to do with these octets, once you've separated them? – Beta Oct 19 '11 at 02:58
  • possible duplicate of [Split string based on delimiter in bash?](http://stackoverflow.com/questions/918886/split-string-based-on-delimiter-in-bash) – David Wolever Oct 19 '11 at 02:59
  • @Beta i need to take two IP addresses from user input arguments (e.g. $1 and $2), search a file list (pre-generated) for an occurrence of $1, and replace it with $2. – brent saner Oct 19 '11 at 03:19
  • 1
    My bash is pretty rusty, but `echo $ip | sed 's/\./\\\./g'` will escape the dots for you... – Beta Oct 19 '11 at 04:44

5 Answers5

18

You could use bash. Here's a one-liner that assumes your address is in $ip:

IFS=. read ip1 ip2 ip3 ip4 <<< "$ip"

It works by setting the "internal field separator" for one command only, changing it from the usual white space delimiter to a period. The read command will honor it.

Rob Davis
  • 15,597
  • 5
  • 45
  • 49
7

If you want to assign each octet to its own variable without using an array or a single variable with newline breaks (so you can easily run it through a for loop), you could use # and % modifiers to ${x} like so:

[ 20:08 jon@MacBookPro ~ ]$ x=192.160.1.1 && echo $x
192.160.1.1
[ 20:08 jon@MacBookPro ~ ]$ oc1=${x%%.*} && echo $o1
192
[ 20:08 jon@MacBookPro ~ ]$ x=${x#*.*} && echo $x
160.1.1
[ 20:08 jon@MacBookPro ~ ]$ oc2={x%%.*} && echo $o2
160
[ 20:08 jon@MacBookPro ~ ]$ x=${x#*.*} && echo $x
1.1
[ 20:08 jon@MacBookPro ~ ]$ oc3=${x%%.*} && echo $o3
1
[ 20:08 jon@MacBookPro ~ ]$ x=${x#*.*} && echo $x
1
[ 20:08 jon@MacBookPro ~ ]$ oc4=${x%%.*} && echo $oc4
1

[ 20:09 jon@MacBookPro ~ ]$ echo "$oc1\.$oc2\.$oc3\.$oc4"
192\.160\.1\.1

See this /wiki/Bash:_Append_to_array_using_while-loop
and more in this article.

chown
  • 51,908
  • 16
  • 134
  • 170
  • this will work nicely.. if nothing cleaner shows up in an hour or so, i'll mark yours as accepted answer. thanks! – brent saner Oct 19 '11 at 03:24
2

You can split strings using the set built-in, with IFS as separator (normally space and tab).

splitip () {
    local IFS
    IFS=.
    set -- $*
    echo "$@"
}

splitip 12.34.56.78
# Now $1 contains 12, $2 contains 34, etc

If you just need to backslash-escape the dots, use string substitution - bash has ${ip//./\\.}

tripleee
  • 175,061
  • 34
  • 275
  • 318
1

This code is something that I found on another site when I was looking to do the same thing. Works perfectly for my application.

   read ICINGAIPADDRESS
# The following lines will break the ICINGAIPADDRESS variable into the four octets 
# and assign each octet to a variable.

ipoct1=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $1 }')
ipoct2=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $2 }')
ipoct3=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $3 }')
ipoct4=$(echo ${ICINGAIPADDRESS} | tr "." " " | awk '{ print $4 }')
Kyle
  • 19
  • 2
  • For a full `awk` solution, you can skip `tr` entirely and set `.` as input separator: `awk -F. '{print $1}'`... – aff Nov 01 '18 at 05:54
0

The easier way is using AWK:

echo 192.168.0.12 | awk -F. '{print $1 $2 $3 $4}'

-F is a field separator, in this case we use the dot "." as separator and print each column individually.

mortiz@florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $1 $2 $3 $4}'
76220156100
mortiz@florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $1}'
76
mortiz@florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $2}'
220
mortiz@florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $3}'
156
mortiz@florida:~/Documents/projects$ echo 76.220.156.100 | awk -F. '{print $4}'
100
Miguel Ortiz
  • 1,412
  • 9
  • 21