How to assign array length to a variable in bash - bash

I'm trying to write a simple bash script that adds integers and supplies the sum. I figured the easiest way would be to assign the input to an array. Then traverse the array to perform the summation. I need to use the length of the array in my for loop and cannot figure out how to assign the array length to a variable.
Any help appreciated on the simple script (which I did to learn bash)
#!/bin/bash
# add1 : adding user supplied ints
echo -n "Please enter any number of integers: "
read -a input
echo "Your input is ${input[*]}"
echo "${#input[#]} number of elements"
num = ${#input[#]} # causing error
for ((i = 0; i < "${num}"; ++i )); do # causing error
sum = $((sum + input[$i]))
done
echo "The sum of your input is $sum"
Which yields the errors:
line 10: num: command not found
line 11: ((: i < :syntax error: operand expected (error token is "< ")

You just have a syntax error. Remove the space before =:
num = ${#input[#]} # causing error
becomes:
num=${#input[#]} # works
Note that if you assign to a variable in bash using the = operator, there MUST NOT be any space before and after the =
Read this entry about Variable Assignment in the Advanced Bash-Scripting Guide

Related

syntax error: operand expected (error token is "+ ") in bash

I am trying to calculate the sum of numbers entered via command line to my script file. Here is my code
#!/bin/bash
for ((i=0;i<=$#;i++))
do
sum=$(($i + $sum))
done
echo $sum | bc
My terminal input is
bash file.sh 1 2
So the output should be 3 but I am getting
syntax error: operand expected (error token is "+ ")
The actual error reason is because of uninitialized variable sum going through the first iteration of the loop. Initialize the variable before entering the loop.
Also a major logical flaw is that you are not even iterating over the input arguments, but just over the counter i which will produce incorrect results if you pass arguments other than 1 2 from the command-line.
You need to pass over the actual arguments argc and argv (arg count and arg vector: for understanding purposes only) and you don't need bc at all
argc=$#
argv=("$#")
sum=0
for ((i=0; i<${argc}; i++)); do
sum=$((${argv[i]} + $sum))
done
To loop over all command line arguments, you can use the simplified form of the shell for statement:
sum=0
for i do
((sum += i))
done
((sum+=i)) is accepted by bash and many other shells; for a Posix-compatible shell, you can use arithmetic expansion with the : builtin:
: $((sum += i))

How do I subtract 1 from an array item in BASH?

I have a side-project in BASH for fun, and I have this code snippet (ARRAY[0] is 8):
while [ $ALIVE == true ]; do
$ARRAY[0] = ${ARRAY[0]} - 1
echo ${ARRAY[0]}
done
However, it comes back with this error:
line 16: 8[1]: command not found
I just started working in BASH, so I might be making an obvious mistake, but I've searched and searched for an answer to a problem like this and came up with no result.
The smallest change is simply:
ARRAY[0]=$(( ${ARRAY[0]} - 1 ))
Note:
No $ before the name of the variable to assign to (foo=, not $foo=)
No spaces around the = on the assignment
$(( )) is the syntax to enter a math context (and expand to the result of that operation).

Random word Bash script if a number is supplied as the first command line argument then it will select from only words with that many characters

I am trying to create a Bash script that
- prints a random word
- if a number is supplied as the first command line argument then it will select from only words with that many characters.
This is my go at the first section (print a random word):
C=$(sed -n "$RANDOM p" /usr/share/dict/words)
echo $C
I am really stuck with the second section. Can anyone help?
might help someone coming from ryans tutorial
#!/bin/bash
charlen=$1
grep -E "^.{$charlen}$" $PWD/words.txt | shuf -n 1
you have to use a while loop to read every single line of that file and check if the length of a word equals the specified number ( including apostrophes ). In my o.s it is 99171 line ( i.e the file).
#!/usr/bin/env bash
readWords() {
declare -i int="$1"
(( int == 0 )) && {
printf "%s\n" "$int is 0, cant find 0 words"
return 1
}
while read getWords;do
if [[ ${#getWords} -eq $int ]];then
printf "%s\n" "$getWords"
fi
done < /usr/share/dict/words
}
readWords 20
this function takes a single argument. the declare command coerces the argument into an integer, if the argument is a string , it coerces it into a number which is 0 . Since we don't have 0 words if the specified argument ( number ) is 0 ( or a string coerced to 0 ) return from the function.
Read every single line in /usr/share/dict/words, get the length of each line with ${#getWords} ( $# >> gives the length of a string/commandline parameters/array size ) check if it equals the specified argument ( number )
A loop is not required, you can do something like
CH=$1; # how many characters the word must have
WordFile=/usr/share/dict/words; # file to read from
# find how many words that matches that length
TOTW=$(grep -Ec "^.{$CH}$" $WordFile);
# pick a random one, if you expect more than 32767 hits you
# need to do something like ($RANDOM+1)*($RANDOM+1)
RWORD=$(($RANDOM%$TOTW+1));
#show that word
grep -E "^.{$CH}$" $WordFile|sed -n "$RWORD p"
Depending on things you probably need to add checks for things like that $1 is a reasonable number, the file exist, that TOTW is >0 and so on.
This code would achieve what you want:
awk -v n="$1" 'length($0) == n' /usr/share/dict/words > /tmp/wordsHolder
shuf -n 1 /tmp/wordsHolder
Some comments: by using "$RANDOM" (as you did on your original script attempt), one would generate an integer on the range 0 - 32767, which could be more (or less) than the number of words (lines) available, given the desired number of characters on a word -- thus, potential for errors here.
To avoid that, we are using a shuf syntax that will retrieve a (sub)randomly picked word (line) on the file using its entire range (from line 1 - last line of file).

confirm numeric character of variable

I need to do an operation but something is wrong in my code in bash
I have 4 variables, km1, km2, km3, km4.
I want to sum the 4 variables except when the value is "CLOSED"
3.200
CLOSED
1.800
0.600
When I do the following sum, there is an error...I thing my variables are not numeric, any help? How can I force them to be numeric and then do the sum?
let km=$km1+$km3+$km4
echo $km
./sum.sh: line 41: let: km=3.200: syntax error: invalid arithmetic operator (error token is ".200")
km1=3.200
km2=CLOSED
km3=1.800
km4=0.600
total=`LC_ALL=C echo "$km1 $km2 $km3 $km4"|awk '{sum += $1+$2+$3+$4}END {print sum}'`
Not that good with awk but i think the above can help. total the is sum of all vars
There are 2 issues with you code. The first one is that you are trying to work with values other than integers. Bash only does integers. You can round up the values to integers using bc (An arbitrary precision calculator language). The second issue is that you are trying to do math on strings. So consider the code below:
#!/bin/bash
km1=3.200;
km2="CLOSED";
km3=1.800;
km4=0.600;
km1=$(echo "$km1/1" | bc)
km3=$(echo "$km3/1" | bc)
km4=$(echo "$km4/1" | bc)
array=($km1 $km2 $km3 $km4)
for i in ${array[#]}; do
case $i in
*[0-9]*)
(( result+=$i ))
esac
done
echo $result

Passing value of a variable to another variable

I'm trying to make a function that will output fibonacci numbers. This is the code:
#!/bin/bash
a1=0;
a2=1;
echo "Vnesi n"
read n
echo $a1
echo $a2
for ((i = 1; i <= $n; i++)) do
a3=$(($a1+$a2))
echo $a3
$a1=$a2
$a2=$a3
done
When I run it, it gets to to line 10 (echo $a3) and then outputs an error:
1
0
1
1
./fib.sh: line 11: 0=1: command not found
./fib.sh: line 12: 1=1: command not found
Basically what I'm trying to do is to pass value from a2 to a1 and value from a3 to a2. What am I doing wrong here?
Your first variable assignments are correct:
a1=0
a2=1
The second ones incorrectly prefix the left-hand side with a dollar sign:
$a1=$a2 # Should be a1=$a2
$a2=$a3 # Should be a2=$a3
replace
$a1=$a2
$a2=$a3
with
a1=$a2
a2=$a3
a1=$a2
not $a1
otherwise the left side is evaluated and the value (0 or whatever) is used

Resources