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

从命令行接受数字并执行函数直到数字为1的Bash脚本,bash,Bash,我正在尝试制作一个bash脚本,该脚本从命令行接收一个数字(介于1和50之间)。如果该数字为偶数,则将其除以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

我正在尝试制作一个bash脚本,该脚本从命令行接收一个数字(介于1和50之间)。如果该数字为偶数,则将其除以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

我在网上查看了错误的含义,但找不到答案。有人能帮帮我吗。

除了在
[i%2-eq 0]
[“$1”-lt 50]
中缺少空格外,您的算术用法不正确,还有几个变量赋值问题。您需要将算术结果分配给手头的值。表单是
var=value
,而不是
value==var

对于如何在bash中执行算术,您有3种选择。旧的
newval=$(expr i/2)
让newval=“$i”/2
newval=$((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))

看起来您还打算:

if [ "${#1}" -gt 1 ] && [ "${#1}" -lt 50 ]
要检查给定的字符数是否介于
1
50
之间,否则,您的
为i,单位为$1;do
没有多大意义。如果您只是测试值而不是字符数,请将的
全部去掉:

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
或者,使用复合命令以更紧凑的形式重写:


除了在
[i%2-eq 0]
[“$1”-lt 50]
中缺少空格外,您的算术使用不正确,还存在一些变量赋值问题。您需要将算术结果分配给手头的值。表单是
var=value
,而不是
value==var

对于如何在bash中执行算术,您有3种选择。旧的
newval=$(expr i/2)
让newval=“$i”/2
newval=$((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))

看起来您还打算:

if [ "${#1}" -gt 1 ] && [ "${#1}" -lt 50 ]
要检查给定的字符数是否介于
1
50
之间,否则,您的
为i,单位为$1;do
没有多大意义。如果您只是测试值而不是字符数,请将
全部去掉:

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

# 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
#/bin/bash
#指定位置参数
num=“$1”
如果((num>1&&num<50));然后
而((num!=1));做
如果((num%2==0));那么#数字是偶数
((num/=2))#复合赋值:与num=num/2相同
否则,数字是奇数
((num=num*3+1))
fi
printf“编号为%d\n”“$num”
完成
fi
这使得在条件和计算中大量使用算术表达式
(…)
。事实上,我从来没有使用过测试构造
[…]
。如果我使用它,我甚至可以在表达式中赋值,例如,
((num=num*2))
而不是
num=$((num*2))

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

代码中无法工作的内容
  • 注释以
    开头,而不是以
    /
    开头
  • 测试构造
    […]
    需要空格:
    [“$1”-gt 1]
  • for
    循环只将
    $1
    分配给
    i
    ,没有其他分配
  • [i%2-等式0]
    比较文本
    i%2
    ,而不是变量
    i
    模2的结果;你需要
    [$((i%2))-eq 0]
    ,或者
    ((i%2==0))
  • 赋值
    i/2==i
    将尝试使用参数
    =
    i
    执行命令
    i/2
    ,但几乎没有成功。您需要
    i=$((i/2))
    ((i/=2))
  • echo“i,
    只打印
    i,
    。您需要
    回显“$i”,
  • 有关赋值
    3*i+1==i
    ,请参见上文

仅根据您的要求,我将按以下方式解决此问题:

#!/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
#/bin/bash
#指定位置参数
num=“$1”
如果((num>1&&num<50));然后
而((num!=1));做
如果((num%2==0));那么#数字是偶数
((num/=2))#复合赋值:与num=num/2相同
否则,数字是奇数
((num=num*3+1))
fi
printf“编号为%d\n”“$num”
完成
fi
这使得在条件和计算中大量使用算术表达式
(…)
。事实上,我从来没有使用过测试构造
[…]
。如果我使用它,我甚至可以在表达式中使用
((num=num*2))而不是赋值