Bash 顺序列出数字 1-1000 的脚本,黄色为赔率,绿色为偶数,蓝色为素数

Bash Script that lists numbers 1-1000 sequentially with odds being in yellow, even in green, and primes in blue

显然这是一个 class 作业。我已经玩了几天了。我很容易让奇数和偶数方面工作得很好,但我一直遇到质数方面的问题。

这是odd/even并且有效

  #!/bin/bash
  for i in $(seq 1000)
  do
    if (($i % 2));then  #even
        echo -e "\e[32m$i\e[0m"  #green

    else  #odd
        echo -e "\e[33m$i\e[0m"  #yellow

    fi
  done

这是 odd/even/prime 的,我无法让它工作。

  #!/bin/bash
  for i in $(seq 1000)
  do
    if (($i % 2));then  #even
            if
                    ($i -eq factor {2..1000})
                            echo -e "\e[34m$i\e[0m" #blue
            else
                    echo -e "\e[32m$i\e[0m"  #green
            fi
    else  #odd
            if
                    ($i -eq factor {2..1000})
                            echo -e "\e[34m$i\e[0m" #blue
            else
                    echo -e "\e[33m$i\e[0m"  #yellow
            fi
    fi
  done

这只是我最近的尝试。我尝试了几种不同的方法,但没有用。一点帮助将不胜感激。也许我做的完全错了,也许我很接近,但我花了很多时间研究这个并且似乎永远无法将它应用到我的脚本中。

遵循质数伪代码 - https://en.wikipedia.org/wiki/Primality_test#Pseudocode ,很容易将其移植到 BASH 脚本:

#! /bin/bash

# Given an integer as an argument
# return 1 if the number is prime, 0 otherwise
function isPrime
{
    number=

    if [ $number -le 3 ]; then
        if [ $number -gt 1 ]; then
            return 1
        else
            return 0
        fi
    elif [ $(( $number % 2 )) -eq 0 ] || [ $(( $number % 3 )) -eq 0 ]; then
        return 0
    fi

    i=5
    while [ $(( $i * $i )) -le $number ]; do
        iplus2=$(( $i + 2 ))
        if [ $(( $number % $i )) -eq 0 ] || [ $(( $number % $iplus2 )) -eq 0 ]; then
            return 0
        fi
        i=$(( $i + 6 ))
    done

    return 1
}

没有必要在数值表达式中使用 $$var 符号,例如:$(( x + 1 )) 是可以的,但我故意把它留在那里,因为我认为它代码的操作对于非脚本编写者来说更明显 reader.

BASH 函数不能真正 return 传统编程意义上的值,它基本上是一种退出代码之类的东西。所以 "returned" 值必须通过 $?.

获得
isPrime 
primal=$?
if [ $primal -eq 1 ]; then
    echo " is prime"
else
    echo " is not prime"
fi

给出输出:

$ ./isPrime.sh 7
7 is prime
$ ./isPrime.sh 8
8 is not prime

很简单。

# from 
isPrime() {
    if ((  == 2 ||  == 3 )); then
        return 0  # prime
    fi
    if ((  % 2 == 0 ||  % 3 == 0 )); then
        return 1  # not a prime
    fi
    local i w
    i=5
    w=2
    while (( i * i <=  )); do
        if ((  % i == 0 )); then
            return 1  # not a prime
        fi
        i=$((i + w))
        w=$((6 - w))
    done
    return 0  # prime
}

isEven() {
    ((  % 2 == 0 ))
}


seq 1000 |
while IFS= read -r n; do
   if isPrime "$n"; then
       echo blue "$n"
   elif isEven "$n"; then
       echo green "$n"
   else
       echo yellow "$n"
   fi
done

isPrime 函数只是从 this thread 复制而来,它是 google 中搜索 bash how to check for prime number 的第一个结果。修复了它的 return 值,因此如果数字是素数,它 returns 0(成功),如果数字不是素数,它 return 非零,并更改为仅使用算术扩展。

由于 OP 了解如何使用转义序列在终端上打印彩色输出,我只是做了简单的回显以提高可读性。

@edit 修复了 isPrime 函数中的拼写错误 /while/s/==/<=/
@edit,当然 isEven 函数应该被反转......

使用 factor 确定数字是否为质数的基本方法是可行的,但需要做一些工作来提取信息。这个原始代码的修改版本是一种方法:

#!/bin/bash

# A glob pattern to match 'factor' output that has at least two numbers
# separated by whitespace after a colon (e.g. '30: 2 3 5')
composite_factors_glob='*:*[0-9]*[[:space:]]*[0-9]*'

for i in {1..1000} ; do
    factors=$(factor "$i")
    # shellcheck disable=SC2053
    if (( i > 1 )) && [[ $factors != $composite_factors_glob ]] ; then
        echo -e "\e[34m$i\e[0m" # prime => blue
    elif ((i%2 == 0)) ; then
        echo -e "\e[32m$i\e[0m" # even  => green
    else
        echo -e "\e[33m$i\e[0m" # odd   => yellow
    fi
done

# shellcheck 注释抑制了虚假的 Shellcheck 警告。