However it is possible to just as easily perform such operations using the ksh93 shell. This post will explain what bitwise manipulation and number conversion facilities are available in ksh93 and provide some hopefully useful utilities and examples.
Many programmers are unaware that ksh93 has builtin support for different numeral radices (AKA arithmetic bases) as shown in the following example.
$ print $(( 10 + 20 ))
30
$ print $(( 2#10 + 20 ))
22
$ print $(( 2#10 + 4#20 ))
10
$
Here is an example of how to convert decimal 255 to base 2, base 8 and base 16 respectively using the typeset command.
$ typeset -i2 a=255
$ echo $a
2#11111111
$ typeset -i8 a=255
$ echo $a
8#377
$ typeset -i16 a=255
$ echo $a
16#ff
$
The bitwise manipulation operators in ksh93 are AND, OR, XOR, SHIFT LEFT and SHIFT RIGHT. There are no SHIFT ROTATE or COMPLEMENT operators. The following is the list of supported bitwise operators in decreasing order of precedence which, by the way, is the same as in the C programming language.
<< >> | Bitwise shift left, shift right | |
& | Bitwise AND | |
^ | Bitwise XOR | |
| | Bitwise OR |
The following shell script includes both logical and bitwise operators together with the expected output for each statement. Notice the difference in output between a logical and bitwise operator.
#!/bin/ksh93
integer -i2 a=5
integer -i2 b=6
# expected output 1
print $(( a < b ))
# expected output 0
print $(( a > b ))
# expected output 3
print $(( a ^ b ))
# expected output 4
print $(( a & b ))
# expected output 1
print $(( a && b ))
# expected output 7
print $(( a | b ))
# expected output 1
print $(( a || b ))
$ x=4
$ print $((x << 1))
8
$ print $(( x << 2 ))
16
$ print $(( x >> 1 ))
2
$ print $(( x >> 2 ))
1
#!/bin/ksh93
typeset -i2 mask=255
[[ $# != 2 ]] && {
echo "Usage: $0 ipaddress subnetmask"
exit 1
}
SaveIFS=$IFS
IFS=.
typeset -a IParr=($1)
typeset -a NMarr=($2)
IFS=$SaveIFS
typeset -i2 ip1=${IParr[0]}
typeset -i2 ip2=${IParr[1]}
typeset -i2 ip3=${IParr[2]}
typeset -i2 ip4=${IParr[3]}
typeset -i2 nm1=${NMarr[0]}
typeset -i2 nm2=${NMarr[1]}
typeset -i2 nm3=${NMarr[2]}
typeset -i2 nm4=${NMarr[3]}
echo
echo " IP Address: $1"
echo " Subnet Mask: $2"
echo " Network Address: $((ip1 & nm1)).$((ip2 & nm2)).$((ip3 & nm3)).$((ip4 & nm4))"
echo "Broadcast Address: $((ip1 | (mask ^ nm1))).$((ip2 | (mask ^ nm2))).$((ip3 | (mask ^ nm3))).$(( ip4 | (mask ^ nm4)))"
echo
exit 0
$ ./calculate-address 10.150.12.1 255.255.255.0
IP Address: 10.150.12.1
Subnet Mask: 255.255.255.0
Network Address: 10.150.12.0
Broadcast Address: 10.150.12.255
$ ./calculate-address 10.150.12.1 255.255.254.0
IP Address: 10.150.12.1
Subnet Mask: 255.255.254.0
Network Address: 10.150.12.0
Broadcast Address: 10.150.13.255
#!/bin/ksh93
[[ $# != 1 ]] && {
echo "Usage: $0 ipaddress/netmask"
exit 1
}
SaveIFS=$IFS
IFS="./"
typeset -a IParr=($1)
IFS=$SaveIFS
typeset -i2 ip1=${IParr[0]}
typeset -i2 ip2=${IParr[1]}
typeset -i2 ip3=${IParr[2]}
typeset -i2 ip4=${IParr[3]}
typeset -i2 cidr=${IParr[4]}
typeset -i2 nm1=0 nm2=0 nm3=0 nm4=0
typeset -i quad=$(( cidr / 8 ))
sigbits=$(( cidr % 8 ))
if (( sigbits != 0 )); then
slot=$(( 256 - ( 256 >> $sigbits ) ))
fi
for (( i=1; i < 5; i++ ))
do
nameref nm=nm${i}
if (( quad != 0 )); then
nm=255
(( --quad ))
elif (( quad == 0 )); then
nm=slot
break
fi
done
typeset -i2 mask=255
print " IP Address: $((ip1)).$((ip2)).$((ip3)).$((ip4))"
print " CIDR Netmask Mask: $((nm1)).$((nm2)).$((nm3)).$((nm4))"
print " CIDR Network (Route): $((ip1 & nm1)).$((ip2 & nm2)).$((ip3 & nm3)).$((ip4 & nm4))"
print " Broadcast Address: $((ip1 | (mask ^ nm1))).$((ip2 | (mask ^ nm2))).$((ip3 | (mask ^ nm3))).$((ip4 | (mask ^ n
m4)))"
exit 0
$ ./calculate-address "192.168.21.12/18"
IP Address: 192.168.21.12
CIDR Network Mask: 255.255.192.0
CIDR Network (Route): 192.168.0.0
Broadcast Address: 192.168.63.255