shell函数计算偶数的错误

Jed*_*dja 12 bash scripts functions

对于作业,我必须编写一个函数,当提供一系列数字时,该函数会打印偶数的数量。

我使用了我在之前的作业中使用的一段代码(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
}
Run Code Online (Sandbox Code Playgroud)

des*_*ert 20

您只是忘记在循环$#中用 ( $)替换:elementfor

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
}
Run Code Online (Sandbox Code Playgroud)

现在来测试这个功能:

$ 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
Run Code Online (Sandbox Code Playgroud)


mur*_*uru 18

@dessert找到了核心问题,我来做一些代码审查:

  1. shebang:/usr/bin/bash在 Ubuntu 中没有。它是/bin/bash
  2. 您已经声明sum local并避免污染函数外部的变量命名空间是件好事。此外,您可以使用以下-i选项将其声明为整数变量:

    local -i sum=0
    
    Run Code Online (Sandbox Code Playgroud)
  3. 始终引用您的变量(和参数)!在这个脚本中不是必须的,但是养成一个很好的习惯:

    for element in "$@"
    do
    
    Run Code Online (Sandbox Code Playgroud)

    也就是说,你可以省略in "$@"这里:

    for element
    do
    
    Run Code Online (Sandbox Code Playgroud)

    in <something>未给出时,for循环隐式地循环参数。这可以避免诸如忘记引号之类的错误。

  4. 无需计算然后检查结果。您可以直接在 中进行计算if

    if (( (element % 2) == 0 ))
    then
        ((sum = sum + 1))
    fi
    
    Run Code Online (Sandbox Code Playgroud)

    (( ... ))算术上下文。它比[[ ... ]]执行算术检查更有用,此外您可以省略$before 变量(这使它更容易阅读,恕我直言)。

  5. 如果您将偶数检查部分移动到一个单独的函数中,它可能会提高可读性和可重用性:

    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"
    }
    
    Run Code Online (Sandbox Code Playgroud)