For an assignment I have to write a function that prints the number of even numbers when provided with a sequence of numbers.
I used the piece of code I used for a previous assignment (to print 1
when a number was even and 0
when the number was odd)
My problem now is that my function keeps printing 0
.
What am I doing wrong?
Here's my script:
#!/usr/bin/bash
# File: nevens.sh
# Write a function called nevens which prints the number of even numbers when provided with a sequence of numbers.
# Check: input nevens 42 6 7 9 33 = output 2
function nevens {
local sum=0
for element in $@
do
let evencheck=$(( $# % 2 ))
if [[ $evencheck -eq 0 ]]
then
let sum=$sum+1
fi
done
echo $sum
}
You just forgot to replace
$#
with ($
)element
in thefor
loop:Now to test the function:
@dessert has found the core problem, I'll give some code review:
/usr/bin/bash
in Ubuntu. It's/bin/bash
.It's good that you have declared
sum
local
, and avoided polluting the variable namespace outside the function. Additionally, you can declare it an integer variable using the-i
option:Always quote your variables (and parameters)! It's not necessary in this script, but a very good habit to get into:
That said, you can omit the
in "$@"
here:When
in <something>
is not given, thefor
loop implicitly loops over the arguments. This can avoid mistakes like forgetting the quotes.There's no need to calculate and then check the result. You can directly do the calculation in the
if
:(( ... ))
is the arithmetic context. It's more useful than[[ ... ]]
for performing arithmetic checks, and additionally you can omit the$
before variables (which makes it easier to read, IMHO).If you moved the even-checking part into a separate function, it might improve readability and reusability:
I'm not sure if you're open to other solutions. Also I don't know if you can use external utilities, or if you're purely limited to bash builtins. If you can use
grep
, for example, your function could be a whole lot simpler:This puts each input integer on its own line, and then uses
grep
to count the lines that end in an even digit.Update - @PeterCordes pointed out that we can even do this without grep - just pure bash, so long as the input list contains just well formed integers (with no decimal points):
This works by creating a list called
evens
by filtering out all the odds, then returning the length of that list.