"Attempted assignment to a non-variable" in bash - linux

I'm new to Bash and I've been having issues with creating a script. What this script does is take numbers and add them to a total. However, I can't get total to work.It constantly claims that total is a non-variable despite it being assigned earlier in the program.
error message (8 is an example number being entered)
./adder: line 16: 0 = 0 + 8: attempted assignment to non-variable (error token is "= 0 + 8")
#!/bin/bash
clear
total=0
count=0
while [[ $choice != 0 ]]; do
echo Please enter a number or 0 to quit
read choice
if [[ $choice != 0 ]];
then
$(($total = $total + $choice))
$(($count = $count + 1))
echo Total is $total
echo
echo Total is derived from $count numbers
fi
done
exit 0

Get rid of some of the dollar signs in front of the variable names. They're optional inside of an arithmetic context, which is what ((...)) is. On the left-hand side of an assignment they're not just optional, they're forbidden, because = needs the variable name on the left rather than its value.
Also $((...)) should be plain ((...)) without the leading dollar sign. The dollar sign will capture the result of the expression and try to run it as a command. It'll try to run a command named 0 or 5 or whatever the computed value is.
You can write:
((total = $total + $choice))
((count = $count + 1))
or:
((total = total + choice))
((count = count + 1))
or even:
((total += choice))
((count += 1))

Related

Shell for loop, stopping at declaration

I'm trying to write a for loop that goes from 1 to 10, then calculates ( 1 through 10 mod 5) + 2. After that I want to display it like this (1 to 10 mod 5) + 2 = answer. However i'm getting an error at the beginning of the loop which is a syntax error.
for (( i = 0; i <= 10; i++)); do
calculate=(i % 5) + 2
echo ("("i "% 5) + 2" calculate)
done
Try these changes:
calculate=$(( i % 5 + 2 ))
# $(( ... )) is the shell's way to do arithmetic
echo "($i % 5) + 2 = " $calculate
# $x is a way to refer to the value of variable x
# (also inside a double-quoted string)
The for loop header is actually OK.

Modulus function in bash shell script

for ((i=0; i<lenPT; i++)) do
if [[ $(($lenPT % 2)) == 0]] then
P[i] = "$((K [0] * arrT[i] + K[2] * arrT[i+1]))"
else
P[i] = "$((K[1]*arrT[i-1]+K[3]*arrT[i]))"
fi
done
I got errors saying that "syntax error in conditional expression" and "syntax error near 'then'". What is the error in my conditional statement?
Space matters, see Barmar's answer. You also need a semicolon after the [[ ]] conditional if you want to put then on the same line.
Instead of the cumbersome [[ $(( )) ... ]] combination, you can use the (Bash-only) (( )) conditional, the contents of which are evaluated in an arithmetic context:
if ((lenPT % 2 == 0)); then
You don't even need $lenPT in this construct, lenPT is enough (see Conditional Constructs in the manual for details).
Since the exit status of ((...)) is 1 (not successful) if the expression evaluates to 0, and 0 (successful) otherwise, you could swap the branches and shorten the condition a little:
if ((lenPT % 2)); then
P[i]=$((K[1] * arrT[i-1] + K[3] * arrT[i]))
else
P[i]=$((K[0] * arrT[i] + K[2] * arrT[i+1]))
fi
You need a space before ]].
if [[ $(($lenPT % 2)) == 0 ]]; then
The if ... else that depends on the value of $lenPT is needless, since $lenPT never changes within the loop. The assignments are so similar the if logic can be replaced with arithmetic. Example:
n=$((lenPT % 2))
for ((i=0; i<lenPT; i++))
do
P[i]="$((K[n] * arrT[i-n] + K[2+n] * arrT[i+1-n]))"
done

if: Expression syntax Error in csh - not to accept other string than the only string it must accept

There's this daemon with, for ex. 5 types in one script. Now, i want to be able to start/stop it by specifying the number of the daemon(to start one by one), OR specify "all" (to start in bulk).
The format: (runscript) (commandName) (daemon # or "all")
Need to satisfy two conditions, when the user inputs: (1) correctly (either by number or "all) OR
(2) incorrectly (either inputted num is greater than $count or all other string than "all").
All conditions are already achieved except for one, if the user inputs other string than "all"
Sample code:
case 'startDaemon': #commandName
set count = 5
if ($#argv == 2 && $2 == all) then
echo "correct, do this"
else if ($#argv == 2 && $2 < $count) then
echo "correct too, do this"
else if ($#argv == 2 && ($2 != all || $2 >= $count)) then
echo "Incorrect parameter: specify daemon # less than $count or 'all' to start all."
else
echo "Please use: $0(runscript) $1(commandname) (daemon # or all)"
whenever I type: (runscript) startDaemon hello, for example, error shows:
if: Expression syntax
When it should have gone to the 3rd condition. Please help and kindly point out if the prob is in the conditions or logical operators or whatever. Thanks in advance
PS. Im using csh. The script given to me is in csh, so yep.
The immediate problem is the comparison $2 < $count, which is invalid when $count contains a string.
Here is a working solution:
#!/bin/csh
set count = 5
if ($#argv == 2) then
if ($2 == all) then
echo "correct, do this"
else if (`echo $2 | grep '^[0-9]*$'`) then
if ($2 < $count) then
echo "correct too, do this"
else
echo "Number must be less than 5"
endif
else
echo "Incorrect parameter: specify daemon # less than $count or 'all' to start all."
endif
else
echo "Please use: $0(runscript) $1(commandname) (daemon # or all)"
endif

Why does this c-shell script stop?

The script is supposed to print "Enter the nest number to add: " and keep doing this until the user enters a negative number. At which point it is supposed to print the sum of the positive numbers. However as is the loop asks for the next number one time, it is entered, and then does not ask again, the script just stops doing anything and doesn't even reach the next line within the loop.
#!/bin/csh -x
#
# This script adds positive numbers entered by the user, stopping
# when a negative number is added
# Usage: +#, +#, +#... -#.
#
# x=0
# sum = 0
while($x>= 0)
echo -n "Enter the next number to be added: "
# sum = $sum + $<
# x = $<
end
#
exit 0
$< reads a line from stdin. This must be assigned to a variable, else if $< is used a second time the script will expect further input before continuing.
# x=0
# sum = 0
while ($x >= 0)
echo -n "Enter the next number to be added: "
# x = $<
if ($x >= 0) then
# sum = $sum + $x
endif
end
echo $sum
exit 0

Problem with bash code

function dec_to_bin {
if [ $# != 2 ]
then
return -1
else
declare -a ARRAY[30]
declare -i INDEX=0
declare -i TEMP=$2
declare -i TEMP2=0
while [ $TEMP -gt 0 ]
do
TEMP2="$TEMP%2"
#printf "%d" "$TEMP2"
ARRAY[$INDEX]=$TEMP2
TEMP=$TEMP/2
INDEX=$[ $INDEX + 1 ] #note
done
for (( COUNT=INDEX; COUNT>-1; COUNT--)){
printf "%d" "${ARRAY[$COUNT]}" <<LINE 27
#echo -n ${ARRAY[$COUNT]} <<LINE 28
}
fi
}
why is this code giving this error
q5.sh: line 27: ARRAY[$COUNT]: unbound variable
same error comes with line 28 if uncommented
One more question, I am confused with the difference b/w '' and "" used in bash scripting any link to some nice article will be helpfull.
It works fine for me except that you can't do return -1. The usual error value is 1.
The error message is because you have set -u and you're starting your for loop at INDEX instead of INDEX-1 (${ARRAY[INDEX]} will always be empty because of the way your while loop is written). Since you're using %d in your printf statement, empty variables will print as "0" (if set -u is not in effect).
Also, it's meaningless to declare an array with a size. Arrays in Bash are completely dynamic.
I would code the for loop with a test for 0 (because the -1 looks confusing since it can't be the index of an numerically indexed array):
for (( COUNT=INDEX - 1; COUNT>=0; COUNT--))
This form is deprecated:
INDEX=$[ $INDEX + 1 ]
Use this instead:
INDEX=$(( $INDEX + 1 ))
or this:
((INDEX++))
I also recommend using lower case or mixed case variables as a habit to reduce the chance of variable name collision with shell variables.
You're not using $1 for anything.

Resources