对于一项作业,我必须编写一个函数,当提供一系列数字时,该函数会打印偶数的数量。
我使用了之前作业中使用的一段代码(用于打印1
数字为偶数和0
奇数时的情况)
我现在的问题是我的函数一直在打印0
。我做错了什么?
这是我的脚本:
#!/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
}
答案1
您只是忘了在循环$#
中用 ( $
)替换:element
for
function nevens {
local sum=0
for element in $@; do
let evencheck=$(( element % 2 ))
if [[ $evencheck -eq 0 ]]; then
let sum=sum+1
fi
done
echo $sum
}
现在测试该功能:
$ nevens 42 6 7 9 33
2
$ nevens 42 6 7 9 33 22
3
$ nevens {1..10..2} # 1 to 10 step 2 → odd numbers only
0
$ nevens {2..10..2} # 2 to 10 step 2 → five even numbers
5
答案2
@甜点找到核心问题后,我来给出一些代码回顾:
- 概要:Ubuntu 中没有
/usr/bin/bash
。它是/bin/bash
。 声明了 很好
sum
local
,避免了污染函数外部的变量命名空间。此外,您可以使用以下-i
选项将其声明为整数变量:local -i sum=0
一定要引用你的变量(和参数)!在这个脚本中这不是必需的,但是养成一个非常好的习惯:
for element in "$@" do
也就是说,你可以省略
in "$@"
这里:for element do
当
in <something>
没有给出时,for
循环会隐式地循环遍历参数。这可以避免诸如忘记引号之类的错误。无需计算然后检查结果。您可以直接在中进行计算
if
:if (( (element % 2) == 0 )) then ((sum = sum + 1)) fi
(( ... ))
是算术语境。它比执行算术检查更有用[[ ... ]]
,另外您还可以省略$
之前的变量(在我看来,这使得它更容易阅读)。如果将均匀检查部分移到单独的函数中,可能会提高可读性和可重用性:
function evencheck { return $(( $1 % 2 )) } function nevens { local -i sum=0 for element do # `if` implicitly checks that the returned value/exit status is 0 if evencheck "$element" then (( sum++ )) fi done echo "$sum" }
答案3
我不确定您是否愿意接受其他解决方案。另外,我不知道您是否可以使用外部实用程序,或者您是否仅限于使用 bash 内置程序。grep
例如,如果您可以使用,您的函数可能会简单得多:
function nevens {
printf "%s\n" "$@" | grep -c '[02468]$'
}
将每个输入整数放在其自己的行上,然后用来grep
计算以偶数结尾的行数。
更新 - @PeterCordes 指出我们甚至可以不使用 grep 来做到这一点 - 只需纯 bash,只要输入列表包含格式正确的整数(没有小数点):
function nevens{
evens=( ${@/%*[13579]/} )
echo "${#evens[@]}"
}
它的工作原理是创建一个列表,evens
过滤掉所有的几率,然后返回该列表的长度。