我正在尝试创建一个从命令行(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
我已经在线查看错误的含义,但无法找到答案。有人可以帮助我。
答案 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"/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))
和
newvar=$((i * 3 + 1))
它看起来也像你想要的那样:
if [ "${#1}" -gt 1 ] && [ "${#1}" -lt 50 ]
检查给定的字符数是否在1
和50
之间,否则,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"