Bash脚本,它接受命令行中的数字并执行函数,直到数字为1

时间:2016-03-13 22:52:50

标签: bash

我正在尝试创建一个从命令行(1到50之间)接收数字的bash脚本。如果数字是偶数,那么它将数字除以2,如果数字是奇数,则将它乘以3并加1。然后数字返回函数直到达到数字1。这是我到目前为止所拥有的

#!/bin/bash

//this looks to see if the command line argument, $1, is between 1 and 50
if ["$1" -gt 1 ] && [ "$1" -lt 50]
then
//if $1 is between 1 and 50, it goes into a for loop when it looks to see if it is even or odd. It keeps going until the number 1 is reached, and prints out each number until then
for i in $1; do
    //if $1 is even
    if [i%2 -eq 0]
    then
        i/2 == i  
        echo "i,"
    //if $1 is even
    else 
        3*i+1 == i
        echo "i,"
    fi
done
fi 

当我运行代码时,我收到错误。

$ ./q1.sh 5

./q1.sh: line 3: [5: command not found

我已经在线查看错误的含义,但无法找到答案。有人可以帮助我。

2 个答案:

答案 0 :(得分:2)

只要看看你的要求,我就会解决这个问题:

#!/bin/bash

# Assign positional parameter
num="$1"

if (( num > 1 && num < 50 )); then
    while (( num != 1 )); do
        if (( num % 2 == 0 )); then # Number is even
            (( num /= 2))           # Compound assignment: same as num = num / 2
        else                        # Number is odd
            (( num = num * 3 + 1 ))
        fi
        printf "Number is %d\n" "$num"
    done
fi

这使得对条件和计算大量使用算术表达式(( ... ))。事实上,我从未使用过测试构造[ ... ]。如果我使用它,我甚至可以在表达式中指定,例如(( num = num * 2 ))而不是num=$(( num * 2 ))

注意while循环如何检查我们是否已达到值1。您使用for i in $1尝试它的方式只是将$1分配给i的一种(复杂)方式,但循环只执行一次。

代码中不起作用的东西

  • 评论以#开头,而不是//
  • 测试构造[ ... ]需要空格:[ "$1" -gt 1 ]等。
  • for循环只会将$1分配给i,而不是其他内容。
  • [ i%2 -eq 0 ]比较文字i%2,而不是变量i模2的结果;您需要[ $(( i%2 )) -eq 0 ],或(( i%2 == 0 ))
  • 作业i/2 == i将尝试使用参数i/2==执行命令i - 但收效甚微。您需要i=$(( i/2 ))(( i /= 2 ))
  • echo "i,"只打印i,。你想要echo "$i,"
  • 有关作业3*i+1 == i,请参阅上文。

答案 1 :(得分:0)

除了错过[ i%2 -eq 0 ][ "$1" -lt 50 ]中的空格外,您的算术运算不正确以及多个变量赋值问题。您需要将算术结果分配给手头的值。表单为var=value,而非value == var

你有两个选择如何在bash中进行算术运算。旧newval=$(expr i / 2)let newval="$i"/2newval=$((i / 2))

清理脚本,您可以执行以下操作:

if [ "$1" -gt 1 ] && [ "$1" -lt 50 ]
then
    for i in $1; do
        //if $i is even
        if (( i % 2 == 0 ))
        then
            newvar=$((i / 2))
            echo "$newvar,"
        //if $i is odd
        else 
            newvar=$((3 * i + 1))
            echo "$newvar,"
        fi
    done
fi

注意,虽然您可以乘以并重新分配循环增量i,但最好将结果分配给新变量,例如一些newvar

请注意:

newvar=$((i / 2))

newvar=$((i * 3 + 1))

它看起来也像你想要的那样:

if [ "${#1}" -gt 1 ] && [ "${#1}" -lt 50 ]

检查给定的字符数是否在150之间,否则,for i in $1; do没有多大意义。如果您只是测试值而不是字符数,请完全删除for

if [ "$1" -gt 1 -a "$1" -lt 50 ]
then
    val="$1"              ## assign positinal parameter to variable
    ## if $val is even    ## to avoid subtleties in syntax
    if (( val % 2 == 0 ))
    then
        newvar=$((val / 2))
        echo "$newvar,"
    ## if $val is odd
    else 
        newvar=$((3 * val + 1))
        echo "$newvar,"
    fi
fi

<强>替代

如果我弄清楚你要做什么,那么你可以考虑这样做:

#!/bin/bash

declare -i val
if [ "$1" -gt 1 -a "$1" -lt 50 ]; then
    val="$1"                    # assign val=$1
    while ((val > 0)); do       # loop for val > 0
        if ((val > 1)); then    # set output format
            fmt="%d,"
        else
            fmt="%d"
        fi
        if ((val % 2 == 0))     # if $val is even
        then
            n=$((val / 2))
        else                    # if $val is even
            n=$((val * 3 + 1))
        fi
        printf "$fmt" "$n"
        ((val--))               # decrement val
    done
else
    printf "input value not between 1 and 50\n"
fi

printf "\n"

示例使用/输出

$ bash ql.sh 10
5,28,4,22,3,16,2,10,1,4

或者,使用复合命令

以更紧凑的形式重写
#!/bin/bash

declare -i val
if [ "$1" -gt 1 -a "$1" -lt 50 ]; then          # validate input 1 - 50
    for ((val = $1; val > 0; val--)); do        # loop for val > 0
        ((val > 1)) && fmt="%d," || fmt="%d"    # print format
        ((val % 2 == 0)) && n=$((val / 2)) || n=$((val * 3 + 1)) # even/odd
        printf "$fmt" "$n"
    done
else
    printf "input value not between 1 and 50\n"
fi

printf "\n"