BASH - 使用变量参考参数

时间:2013-07-06 14:59:45

标签: bash variables loops for-loop parameters

我试图制作一个小二进制数来计算二进制数。它的工作原理如下:

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

- 对于每个参数数字:如果它是'1',则将其乘以相应的2的幂(在上面的情况下,最左边的'1'将是64),然后将其加到'sum'变量中

这是代码(注意到它是错误的):

    #!/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行,包括空白行)。在那里,我试图检查EACH参数的内容是否等于1.我如何使用变量来做到这一点?

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

除此之外,我试过这个:'$(echo“$”$ i)'但是没有用。

我知道我的问题很复杂,我尽力让它变得清晰。 有什么帮助吗?

4 个答案:

答案 0 :(得分: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移位后。您实际上也可以使用带有移位的数字来指示移动变量的距离,因此shift就像shift 1,而shift 2会给$1使用的值在$3

答案 1 :(得分: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"

(使用2i将输入基数设置为2,并将101010放在堆栈上并p将其设置为拉。)

或者,如果您更喜欢bc

bc <<< "ibase=2;101010"

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

Pure Bash。

#!/bin/bash

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

使用直流。

#!/bin/bash

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

使用bc。

#!/bin/bash

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

滥用IFS,使用直流。

#!/bin/bash

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

滥用IFS,使用bc。

#!/bin/bash

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

所以我们仍然没有回答你的问题(你对OP的评论中的问题):并找出我们是否以及如何使用变量来引用参数。它是在使用间接扩展进行Bash。您可以在Shell Parameter Expansion section of the Bash reference manual中阅读相关内容。最好的方法是在终端显示:

$ 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

希望这有帮助!

答案 2 :(得分:1)

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

i=2
echo "${!i} is now equivalent to $2"

答案 3 :(得分:0)

也尝试这个:

#!/bin/bash - 
( IFS=''; echo $((2#$*)) )