Attempted assignment to non-variable?

5,724

Solution 1

The problem is that you are attempting to perform parameter substitution by preceding the first positional parameter name with $.

You can accomplish what you want like so:

...
elif [ $1 -lt 1000000 ]
then
    arg="$1"
    let arg/=1000
    echo $arg" "$kilo
fi

As far as I can tell, you can't use the positional parameter directly by saying:

let 1/=1000

because this would be a syntax error.

Incidentally, from your error message, I can see that $1 was set to 28888. You should note that Bash doesn't do floating point arithmetic. You will find arg set to 28 (the quotient of integer division of 28888 by 1000) instead of 28.888. Please see this wonderful Q&A on how to do floating point arithmetic in scripts.

Solution 2

The only way to assign values to positional parameters in bash is via the set builtin:

set a b

assigns a to $1 and b to $2 (note that it resets the whole positional parameter list, so $3, $4... are lost).

So here, you could do:

set -- "$(($1 / 1000))"

To assign the value of $1 divided by 1000 to $1.

By contrast, with zsh (a more advanced Bourne-like shell, not part of the GNU project, found on all Unices though often not by default), you can assign individual positional parameters like:

1=$(($1 / 1000))

Or:

argv[1]=$(($1 / 1000))

Or:

(( argv[1] /= 1000 ))

($argv is a special array tied to the positional parameters there)

You still cannot do:

let 1/=1000
(( 1/=1000 ))

though.

zsh also supports floating point arithmetics, so you can do:

((argv[1] /= 1000.))

(the use a of a floating point constant (1000.) forces floating point arithmetic).

You may want to display it like:

printf "%.2f$kilo\n" $1
Share:
5,724

Related videos on Youtube

user79550
Author by

user79550

Updated on September 18, 2022

Comments

  • user79550
    user79550 over 1 year

    We can use arithmetic operations inside shell script function:

    function mess
    {
       if (( "$1" > 0 )) ; then
          total=$1
       else
          total=100
       fi
       tail -$total /var/adm/messages | more
    }

    I try to do this arithmetic operations on the function args:

    #!/bin/bash
    byte="Bytes"
    kilo="KB"
    mega="MB"
    giga="GB"
    function bytesToUnites() {
    if (( "$1" < 1000 )) 
    then
        echo $1" "$byte
    elif (( $1 < 1000000 ))
    then
        let $1/=1000
        echo $1" "$kilo
    fi
    }
    
    bytesToUnites 28888

    But I get this error:

    line 12: let: 28888/=1000: attempted assignment to non-variable (error token is "/=1000")
    28888 KB

    How can I fix this?

    • Admin
      Admin almost 10 years
      Your placement of " characters is not optimal. In almost all cases, expansion of $var should be inside ", not outside of it. So for example echo $1" "$byte is bad, echo "$1 $byte" is good.
  • user79550
    user79550 almost 10 years
    Thanks I wanted to upvote it but I can't
  • Jeff Hewitt
    Jeff Hewitt almost 10 years
    @user79550 No worries. If the answer properly solves your problem, consider accepting it (click the tick button under the vote buttons) so that others know this question is solved.
  • user79550
    user79550 over 9 years
    I have tried printf "%.2f$kilo\n" $1 as you suggested but it printed 28.00 instead of 28.88 @Stéphane Chazelas
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    @user79550, in zsh? After ((argv[1] /= 1000.)) ?
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    @user79550, you can call any other application (shell or not) that can do floating point arithmetic from your dumb shell (zsh, ksh93, bc, dc, awk, perl, php... see unix.stackexchange.com/questions/40786/…)