6

When I run this script I get this error:

./myscript.sh: 16: arithmetic expression: expecting primary: "1 ** 1"

When I run this shell script with bash, as in #! /bin/bash on the first line, the math works properly; unfortunately I need to use /bin/sh. What am I doing wrong? I'm on Linux Mint if that matters.

#! /bin/sh

x=1
while [ $x -le 10 ]
do
    y=1
    while [ $y -le 10 ]
    do
        echo $(($y ** $x))"   \c"
        y=`expr $y \+ 1`
    done
    echo
    x=`expr $x \+ 1`
done

3 Answers 3

7

Standard shell arithmetic only allows integer arithmetic operations. This doesn't include ** for exponentiation, which bash has as an extension.

Integer exponentiation is easy enough to implement as a shell function (though you'll run into wraparound soon).

pow () {
    set $1 $2 1
    while [ $2 -gt 0 ]; do
      set $1 $(($2-1)) $(($1*$3))
    done
    echo $3
}

As an aside, why use expr here? Shell arithmetic can do addition.

4
  • Wow thank you so much. Another quick question if you don't mind... when writing a bash shell script, what is the bash version of \c... when I put that in it echo's it verbatum instead of the next echo being on the same line.
    – whuff739
    Commented Feb 23, 2011 at 22:09
  • 1
    @whuff739: echo -n. If you want to be portable, use printf %s 'print\this!exactly+with%no$newline*at;the&end'. Commented Feb 23, 2011 at 22:14
  • You should also check out the bc program if you want to stuff other than basic add/multiply/subtract/divide. Example: echo $(echo '2^3' | bc) (using ksh here)
    – Nitrodist
    Commented Feb 23, 2011 at 22:16
  • @Nitrodist, I'll definitely look into that, thanks a lot.
    – whuff739
    Commented Feb 23, 2011 at 22:18
3

I think you're out of luck, as the ** exponent operator isn't standard for /bin/sh. You can use bc, though: echo "$y ^ $x" | bc.

1

The POSIX shell apparently does not have an exponentiation operator. You can roll your own:

pow() {
    local x y res i
    x=$1
    y=$2
    res=1
    i=1
    while [ $i -le $y ]; do
        res=$(( res * x ))
        i=$(( i + 1 ))
    done
    echo $res
}

x=1
while [ $x -le 10 ]; do
    y=1
    while [ $y -le 10 ]; do
        echo "$(pow $y $x)   \c"
        y=$(( y + 1 ))
    done
    echo
    x=$(( x + 1 ))
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .