3

I am trying to create a simple program in Shellscript(Bash) to calculate 2's complement binary numbers.

As a test, I am only using an 8-bit binary value (00000100) but I keep getting a "Bad Substitution" error and I have no idea why.

  #!/bin/bash
binary=00000100
firstBit=${binary:0:1}
secondBit=${binary:1:1}
thirdBit=${binary:2:1}
fourthBit=${binary:3:1}
fifthBit=${binary:4:1}
sixthBit=${binary:5:1}
seventhBit=${binary:6:1}
eighthBit=${binary:7:1}
binaryNew=""
if [[ $firstBit == "1" ]]
then
binaryNew=0
if [[ $secondBit == "1" ]]
then
binaryNew+=0
else 
binaryNew+=1
if [[ $thirdBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
if [[ $fourthBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
if [[ $fifthBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
if [[ $sixthBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
if [[ $seventhBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
if [[ $eighthBit == "1" ]]
then
binaryNew+=0
else
binaryNew+=1
fi
fi
fi
fi
fi
fi
fi
fi
echo $binaryNew=

Any help would be appreciated.

Thanks

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Mr Digs
  • 29
  • 1
  • 4
  • 2
    I'm not getting the error, just `=` as output, as the first bit is 0, so all the rest of the ifs (you should indent the code properly) is skipped. – choroba Dec 16 '17 at 19:54
  • 2
    Run your code with `set -xv` to see what's going on. – choroba Dec 16 '17 at 19:57
  • @choroba I get a bad substitution error using my available Shellscript server. It doesn't seem to like something in that script but I cannot tell what. On your second point: How can I handle the first if statement to move onto the second number if the first one is 0? Obviously, "=" isn't the response I am looking for – Mr Digs Dec 16 '17 at 20:01
  • @MrDigs, I've posted an aswer about "bad substitution" because it is too long to be a comment. I hope it's useful. – Yoory N. Dec 17 '17 at 06:35

5 Answers5

5

To do two's complement on an 8-bit binary value:

$ binary=00000100
$ x=$((2#$binary))
$ [ "$x" -gt 127 ] && ((x=x-256)); echo "$x"
4

Notes

  1. The expression $((2#$binary)) does conversion from binary to decimal.

  2. The commands [ "$x" -gt 127 ] && ((x=x-256)) perform two's complement on an 8-bit value.

John1024
  • 109,961
  • 14
  • 137
  • 171
2

If you want to iterate over a value, use a loop instead of defining a variable for each position:

#! /bin/bash

binary=0100
for ((pos=0 ; pos < ${#binary} ; pos++ )) ; do
    if (( ${binary:$pos:1} )) ; then
        complement+=0
    else
        complement+=1
    fi
done
echo $complement
choroba
  • 231,213
  • 25
  • 204
  • 289
2

With bash, tr and bc:

#!/bin/bash

binary=00000100

# Ones' complement, result decimal
c1=$(tr 01 10 <<< $binary)

# Two's complement, result decimal
c2=$((2#$c1+1))

# convert decimal to binary
echo "obase=2; $c2" | bc

Output:

11111100
Cyrus
  • 84,225
  • 14
  • 89
  • 153
2

I will not answer how to calculate 2's complement in bash. Instead I will answer why the OP's getting the 'Bad substitution' error.

Note the two spaces before the shebang:

  #!/bin/bash

Because of these, it's not interpreted as a shebang, but as a usual line with a comment indented by two spaces.

Because of that, the script is not executed by bash, but by user's default shell, in OP's case it's most likely /bin/sh or whatever it is symlinked to.

You can determine what shell is used by the user as default how suggested here:

getent passwd $LOGNAME | cut -d: -f7
Yoory N.
  • 4,881
  • 4
  • 23
  • 28
1

for arithmetic operation in bash use double parenthesis (( .. )), otherwise some operation can be done if variable declared as integer.

typeset -i binaryNew
binaryNew+=1

or

((binaryNew+=1))

bash arithmetic can only convert from a base between 2 to 62 to base 10, for example

i=$((2#10101))
echo "$i"
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36