2

我试图制作一个将二进制数计算为十进制的小脚本。它是这样工作的:

- 获取 '1' 或 '0' 数字作为 SEPARATE 参数。例如“./bin2dec 1 0 0 0 1 1 1”。

- 对于每个参数位:如果是“1”,则将其乘以相应的 2 的幂(在上述情况下,最左边的“1”将为 64),然后将其添加到“和”变量中。

这是代码(在指出的地方是错误的):

    #!/bin/bash

    p=$((2**($#-1)))  #Finds the power of two for the first parameter.
    sum=0  #The sum variable, to be used for adding the powers of two in it.


    for (( i=1; i<=$#; i++ ))  #Counts all the way from 1, to the total number of parameters.
    do

            if [ $i -eq 1 ]  # *THIS IS THE WRONG POINT* If parameter content equals '1'... 
            then
                    sum=$(($sum+$p))  #...add the current power of two in 'sum'.
            fi

    p=$(($p/2))  #Divides the power with 2, so to be used on the next parameter.
    done


    echo $sum  #When finished show the 'sum' content, which is supposed to be the decimal equivalent.

我的问题在注意点(第 10 行,包括空白行)。在那里,我正在尝试检查每个参数的内容是否等于 1。如何使用变量来执行此操作?

例如,$1 是第一个参数,$2 是第二个参数,以此类推。我希望它像 $i,其中 'i' 是每次增加一的变量,以便它匹配下一个参数。

除其他外,我试过这个:'$(echo "$"$i)' 但没有用。

我知道我的问题很复杂,我努力尽可能地把它说清楚。有什么帮助吗?

4

4 回答 4

2

这个怎么样?

#!/usr/bin/bash

res=0

while [[ $# -gt 0 ]]
do
    res=$(($res * 2 + $1))
    shift
done

echo $res

$ ./bin2dec 1 0 0 1
9

shift是一个命令,它将传递给脚本的每个参数向左移动,将其值减 1,因此 的值$2现在在$1移位后为 at。实际上,您也可以使用 shift 来表示将变量移动多远,shift就像shift 1,并且shift 2会给出$1过去的值 at $3

于 2013-07-06T15:18:05.150 回答
1

要按名称间接引用变量,请使用${!name}

i=2
echo "${!i} is now equivalent to $2"
于 2013-07-06T18:12:21.863 回答
1

这个怎么样?

#!/bin/bash

p=$((2**$#))
while(($#)); do
   ((sum+=$1*(p/=2)))
   shift
done
echo "$sum"

或者这个(朝另一个方向发展):

#!/bin/bash

while(($#)); do
    ((sum=2*sum+$1))
    shift
done
echo "$sum"

请注意,没有错误检查。

请考虑 fedorqui 的评论:用于echo $((2# binary number ))从二进制转换为十进制。

另请注意,如果您提供太多参数,这将很容易溢出。


如果您想要一些不会溢出的东西,请考虑使用dc

dc <<< "2i101010p"

(将输入基数设置为 22i并放入101010堆栈并p对其进行处理)。

或者,如果您bc更喜欢:

bc <<< "ibase=2;101010"

请注意,这些需要将二进制数作为一个参数输入,而不是像您想要的那样将所有数字分开。如果您真的需要将所有数字分开,您还可以使用这些有趣的方法:

纯重击。

#!/bin/bash

echo $((2#$(printf '%s' "$@")))

带直流。

#!/bin/bash

dc <<< "2i$(printf '%s' "$@")p"

与公元前。

#!/bin/bash

bc <<< "ibase=2;$(printf '%s' "$@")"

滥用 IFS,带 dc。

#!/bin/bash

( IFS=; echo "2i$*p" ) | dc

滥用 IFS,与 bc。

#!/bin/bash

( IFS=; echo "ibase=2;$*" ) | bc

所以我们仍然没有回答你的问题(你对 OP 的评论中的那个):并找出我们是否以及如何使用变量来引用参数。它是在 Bash 中通过间接扩展完成的。您可以在 Bash 参考手册的Shell Parameter Expansion部分了解它。最好的办法是在终端中向您展示:

$ a="hello"
$ b=a
$ echo "$b"
a
$ echo "${!b}"
hello

整洁,嗯?与位置参数类似:

$ set param1 param2 param3
$ echo "$1, $2, $3"
param1, param2, param3
$ i=2
$ echo "$i"
2
$ echo "${!i}"
param2

希望这可以帮助!

于 2013-07-06T15:22:19.660 回答
0

也试试这个:

#!/bin/bash - 
( IFS=''; echo $((2#$*)) )
于 2013-07-06T16:14:55.753 回答