newprime.sh: 第 14 行: [: 0+1: 预期的整数表达式

问题描述

我的代码有什么问题?我正在尝试将质数打印到 n 位

 echo Enter Number
    read num
    for (( i=2; $i <= $num ; i++ ))
    do
            c=0
            for (( j=2; $j <= $i ; j++))
            do
                    mod=$(($i % $j))
                    if  [ "$mod" -eq 0 ]
                    then
                            c=`expr $c+1`
                    fi
            done
            if [ "$c" -eq 1 ]
            then
                    echo $c
    
            fi
    done

我不知道我做错了什么。如果有人能告诉我如何解决它,我将不胜感激

newprime.sh: line 14: [: 0+1: integer expression expected
newprime.sh: line 14: [: 0+1: integer expression expected
newprime.sh: line 14: [: 0+1+1: integer expression expected
newprime.sh: line 14: [: 0+1: integer expression expected
newprime.sh: line 14: [: 0+1+1+1: integer expression expected
newprime.sh: line 14: [: 0+1: integer expression expected

解决方法

expr 要求参数作为单独的参数传递。引用 the POSIX standard for expr

应用程序应确保表中的每个表达式运算符符号 [...] 以及符号 integer 和 string 作为单独的参数提供给 expr。

此处的代码将所有运算符附加到一个参数中,因此是您的问题。


因此:

c=$(expr "$c" + 1)

...不是...

c=$(expr $c+1)

但完全不要这样做。写起来更高效、更易读:

c=$(( c + 1 ))
,

优化了更少的迭代POSIX shell版本:

#!/usr/bin/env sh

printf %s 'Enter Number: '
read -r num
i=1
while [ "$i" -le "$num" ]; do
  c=0
  j=2
  # Stop checking division when divisor power 2 is greater than number
  # or we identifed a divisor
  while [ "$((j * j))" -le "$i" ] && [ "$c" -eq 0 ]; do
    c=$((i % j == 0))
    j=$((j + 1))
  done
  if [ "$c" -eq 0 ]; then
    printf '%s\n' "$i"
  fi
  i=$((i + 2))
done

或者使用函数:

#!/usr/bin/env sh

is_prime() {
  j=2
  # Check j is a divisor of argument number,while j^2 is less than number
  while [ "$((j * j))" -le "$1" ]; do
    # If j is a divisor of number before the end of the loop
    # number is not prime,so return 1
    [ "$(($1 % j))" -eq 0 ] && return 1
    j=$((j + 1))
  done
}

printf %s 'Enter Number: '
read -r num
i=1
while [ "$i" -le "$num" ]; do
  if is_prime "$i"; then
    printf '%s\n' "$i"
  fi
  i=$((i + 2))
done
,

不要使用expr。将您的数学表达式放入 (( ))(或 echo $(( )) 以打印结果),shell 将对其进行评估。

看看 expr 的输出与常规 shell 算法相比是什么样的:

$ expr 0+1
0+1
$ echo "$((0+1))"
1
如果两个操作数都不是整数,带有 -eq 或单个方括号(例如 test)的

[ 1 -eq 2 ] 会打印错误。这就是导致您出错的原因。

这是在 bash 中列出素数的一种快速而简洁的方法。你可以把它放在一个函数或脚本中:

for ((i=2; i<="${1:?Maximum required}"; i++)); do
    for ((j=2; j<i; j++)); do
        ((i%j)) || continue 2
    done
    echo "$i"
done

编辑:只是为了解释一些事情,如果 (([expression])) 评估为 0,它返回非零 (1)(失败)。如果计算结果为任何其他数字(正数或负数),则返回零(真)。当一个数整除为 i 时,模数 (%)(余数)为零。因此命令失败,我们知道它不是质数,我们可以 continue 外循环,用于下一个数字。