如何使用位运算符在if语句?(How to use bitwise operators in if

2019-08-06 19:24发布

我想写的东西是这样的:

if [[ ( releases["token"] & $MASK ) -eq 1 ]]; then

但我得到的错误:

意外的标记'&”,有条件的二元运算符预期

我如何使用位运算符在if语句?

Answer 1:

您可以使用Arithmetic Expansion

(((5&3)==1)) && echo YES || echo NO

这将打印YES



Answer 2:

逻辑VS语法

....或者:“有什么话要说吗?”

乍一看,如@ chepner的指出了意见 ,问题可能仅仅是语法的一个,这会导致编译错误( unexpected token '&', conditional binary operator expected )。 而事实上, @千电子伏的回答解决了使用算术扩展 ,它被应用到If声明@古斯塔沃的回答 。

然而,这个问题:“ 如何使用位运算符在if语句”在一个更一般的方式是制定并乞求如何使用位运算符来核对答案$MASK (这是不是“如何避免语法问题使用二进制比较“)时的错误。

事实上,它可以假设的是,示例代码

if [[ ( releases["token"] & $MASK ) -eq 1 ]]; then 

在找到解决办法,并明确标注为“像......”的工作正在进行中。 现在// @千电子伏的任意假设

 releases["token"]=3
 MASK=5

可能隐藏事实,也有在使用逻辑误区-eq 1在首位。 因此,尽管@千电子伏的答案与所选择的价值观的作品,如输入的结果, 4线

 (((5&4)==1)) && echo YES || echo NO

将打印NO,尽管人们所期望的是在该情况下,为45都具有第三位集。

所以这个答案解决了问题,例如这个逻辑上的错误,并尝试一个笼统的回答了这个问题的标题。


首先第一件事情!

...或者:“按位表示的背景”

理解逐位比较是有帮助在它们的位表示的可视化数(列在下面的例子中自上而下):

 |-----------------------------------------------------------| | | hexadecimal representation of the value | | bit val | 0 1 2 3 4 5 6 7 8 9 ABCDEF | |---------|---------------------- bit ----------------------| | | shows if the given value has the given bit set | | 0 | - x - x - x - x - x - x - x - x | | 1 | - - xx - - xx - - xx - - xx | | 2 | - - - - xxxx - - - - xxxx | | 3 | - - - - - - - - xxxxxxxx | |---------|---------------------- val ----------------------| | shows the value that the given bit adds to the number | | 0 1 | 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 | | 1 2 | 0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2 | | 2 4 | 0 0 0 0 4 4 4 4 0 0 0 0 4 4 4 4 | | 3 8 | 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 | |---------|-------------------------------------------------| |sum: 15 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | | | decimal representation of the value | |===========================================================| 

这是由下面的代码片断创建的:

( # start a subshell to encapsulate vars for easy copy-paste into the terminal
  # do not use this in a script!
echo ;
echo "|-----------------------------------------------------------|";
echo "|         |     hexadecimal representation of the value     |";
echo "| bit val |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F |";
echo "|---------|---------------------- bit ----------------------|";
echo "|         |  shows if the given value has the given bit set |";
mask=0;
for (( bit=0; bit<4; bit++)); do
    mask=$((1<<bit));
    echo -n "|  $bit      |"
    for ((x=0;x<16;x++)); do ((((x&mask)>0))&&echo -n '  x'||echo -n '  -'); done
    echo " |";
done ;
echo "|---------|---------------------- val ----------------------|";
echo "|     shows the value that the given bit adds to the number |";
mask=0;
for (( bit=0; bit<4; bit++)); do
    mask=$((1<<bit));
    echo -n "|  $bit   $mask  |"
    for ((x=0;x<16;x++)); do echo -n "  $((x&mask))"; done
    echo " |";
done ;
echo "|---------|-------------------------------------------------|";
echo "|sum:  15 |  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 |";
echo "|         |       decimal representation of the value       |";
echo "|===========================================================|";
echo ;
)


的好奇壳体3 & 5 VS 4 & 5

...或: “ ==1 VS >0和的差异&| ,和^

如果现在我们检查所提到的例子的特殊情况,我们将看到的缺点:

 |------------------ value: 3 / mask: 5 -------------------| | | value | mask | and | or | xor | xnor | | | 3 | 5 | 3 & 5 | 3 | 5 | 3 ^ 5 | | | bit val |bit:val|bit:val|bit:val|bit:val|bit:val|bit:val| |---------|-------|-------|-------|-------|-------|-------| | 0 1 | 1 1 | 1 1 | 1 1 | 1 1 | 0 0 | 0 0 | | 1 2 | 2 1 | 0 0 | 0 0 | 1 2 | 1 2 | 1 2 | | 2 4 | 0 0 | 4 1 | 0 0 | 1 4 | 1 4 | 1 4 | | 3 8 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | |---------|-------|-------|-------|-------|-------|-------| |sum: | 3 | 5 | ==> 1 | 7 | 6 | 6 | |---------|-----------------------------------------------| |check: | 3 & 5 == 1 ? YES | | | | 3 & 5 >= 1 ? YES | ==> 3 & 5 > 0 ? YES | |=========================================================| |------------------ value: 4 / mask: 5 -------------------| | | value | mask | and | or | xor | xnor | | | 4 | 5 | 4 & 5 | 4 | 5 | 4 ^ 5 | | | bit val |bit:val|bit:val|bit:val|bit:val|bit:val|bit:val| |---------|-------|-------|-------|-------|-------|-------| | 0 1 | 0 0 | 1 1 | 0 0 | 1 1 | 1 1 | 1 1 | | 1 2 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | | 2 4 | 4 1 | 4 1 | 1 4 | 1 4 | 0 0 | 0 0 | | 3 8 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | 0 0 | |---------|-------|-------|-------|-------|-------|-------| |sum: | 4 | 5 | ==> 4 | 5 | 1 | 1 | |---------|-----------------------------------------------| |check: | 4 & 5 == 1 ? NO | | | | 4 & 5 >= 1 ? YES | ==> 4 & 5 > 0 ? YES | |=========================================================| 


请特别注意以下检查:

 |---------|-----------------------------------------------| |check: | 3 & 5 == 1 ? YES | | | | 3 & 5 >= 1 ? YES | ==> 3 & 5 > 0 ? YES | ---------|------------------------------------------------| |check: | 4 & 5 == 1 ? NO | | | | 4 & 5 >= 1 ? YES | ==> 4 & 5 > 0 ? YES | |---------|-----------------------------------------------| 


输出上述由以下代码段创建的:

( # start a sub-shell to encapsulate vars for easy copy-paste into the terminal
  # do not use this in a script!
echo ;
for o in 3 4; do
echo "|------------------ value: $o / mask: 5 -------------------|";
echo "|         | value | mask  |  and  |  or   |  xor  | xnor  |";
echo "|         |   $o   |   5   | $o & 5 | $o | 5 | $o ^ 5 |       |";
echo "| bit val |bit:val|bit:val|bit:val|bit:val|bit:val|bit:val|";
echo "|---------|-------|-------|-------|-------|-------|-------|";
mask=0;
for (( bit=0; bit<4; bit++)); do
    mask=$((1<<bit));
    echo -n "|  $bit   $mask "
    echo -n " | $(($o&mask))   $((($o&mask)>0))"
    echo -n " | $((5&mask))   $(((5&mask)>0))"
    echo -n " | $(((($o&mask)&(5&mask))>0))   $((($o&mask)&(5&mask)))"
    echo -n " | $(((($o&mask)|(5&mask))>0))   $((($o&mask)|(5&mask)))"
    echo -n " | $(((($o&mask)^(5&mask))>0))   $((($o&mask)^(5&mask)))"
    echo -n " | $(((($o&mask)^(5&mask))>0))   $((($o&mask)^(5&mask)))"
    echo " |";
done ;
echo "|---------|-------|-------|-------|-------|-------|-------|";
echo -n "|sum:     |     $o |     5 |";
echo " ==> $(($o&5)) |     $(($o|5)) |     $(($o^5)) |     $(($o^5)) |";
echo "|---------|-----------------------------------------------|";
echo -n "|check:   |  $o & 5 == 1 ? $(((($o&5)==1))&&echo YES||echo "NO ")     ";
echo "|                       |";
echo -n "|         |  $o & 5 >= 1 ? $(((($o&5)>=1))&&echo YES||echo "NO ")     ";
echo "| ==>  $o & 5 > 0 ? $(((($o&5)>0))&&echo YES||echo "NO ")  |";
echo "|=========================================================|";
echo ;
done
echo ;
)


你好,世界!

...或者:“上升和光泽!”

那么,如何才能做到这一点了吧? 让我们想象一下,我们有以下选项设置:

 # option set: option_1=1 option_2=2 option_3=4 option_4=8 option_5=16 option_6=32 option_7=64 option_8=128 option_9=256 


比如,我们可以设置选择这些选项的功能,并返回结合的编码作为返回值。 或者反过来:通过选项的选择作为一个数字参数。 无论你使用的情况是,该方案将被加在一起:

 # set options: option = option_1 + option_4 + option_5 + option_9 


我们如何最好检查一下,该选项被设置( 145 ,和9 )? 这再次当然取决于你的使用情况,但我还挺喜欢的case构建! 就像是 ...

 case $option in 0) echo "no option set!";; 1) echo "option 1";; 2) echo "option 2";; 3) echo "option 1 and 2";; *) echo "...";; esac 

可以工作,但不是很好,因为我们将不得不建立每个组合!


最终获胜者是 ...

...或者:“真正的Case

我们可以使用case的,而不是通过以下方式...

 echo "check for options using >0:" case 1 in $(( (option & option_1) >0 )) ) echo "- option_1 is set";;& $(( (option & option_2) >0 )) ) echo "- option_2 is set";;& $(( (option & option_3) >0 )) ) echo "- option_3 is set";;& $(( (option & option_4) >0 )) ) echo "- option_4 is set";;& $(( (option & option_5) >0 )) ) echo "- option_5 is set";;& $(( (option & option_6) >0 )) ) echo "- option_6 is set";;& $(( (option & option_7) >0 )) ) echo "- option_7 is set";;& $(( (option & option_8) >0 )) ) echo "- option_8 is set";;& $(( (option & option_9) >0 )) ) echo "- option_9 is set";;& esac 

请注意

  • 内的空间$(( (option & option_1) >0 )) )是完全任选的,并且被添加以提高可读性。 最后收托架)是用于case构建体。
  • 命令列表 s的终止;;&中,为了继续评估下一个选项测试。 如果你想abord列表进行进一步的处理,设置option=0或当前的option=option_X

...我们得到以下结果:

 check for options using >0: - option_1 is set - option_4 is set - option_5 is set - option_9 is set 

欢呼! :-)


而且if我是一个富有的人!

 echo "# to use it in an if statement:"; if (((option&option_5)>0)); then echo "- option_5 is set" else echo "- option_5 is NOT set" fi # to use it in an if statement: - option_5 is set 


但最后穷人的条件:

 echo "# or to use it just for conditional execution:"; (((option&option_6)>0)) \ && echo "- option_6 is set" \ || echo "- option_6 is NOT set" # or to use it just for conditional execution: - option_6 is NOT set 


“谁不回答这些问题已经通过了测试。”

...或者:“留下来,”他说,“这只是一个测试。”

(卡夫卡,1975:181)

因此,这将是完全有可能使用该解决方案,张贴在的问题,通过细微变化如下:

 ( declare -A releases=([token]=4) declare -i MASK=5 if [[ $(( releases["token"] & $MASK )) -gt 0 ]]; then echo YES else echo NO fi ) 

的变化如下: -使用$(())而不是()做了测试,这将返回按位比较的价值-使用-gt 0 ,而不是-eq 1


干脆在行动:

( # start a sub-shell to encapsulate vars for easy copy-paste into the terminal
  # do not use this in a script!
echo ;

for ((i=0; i<9;i++)); do
    o="option_$((i+1))"
    declare -i $o=$((1<<$i))
    echo "$o = ${!o}"
done

echo ;
echo ;

echo "# set options:"
echo "option = option_1"
echo "       + option_4"
echo "       + option_5"
echo "       + option_9"

option=option_1+option_4+option_5+option_9

echo ;
echo ;

echo "check for options using >0:"
case 1 in
  $(( (option & option_1) >0 )) ) echo "- option_1 is set";;&
  $(( (option & option_2) >0 )) ) echo "- option_2 is set";;&
  $(( (option & option_3) >0 )) ) echo "- option_3 is set";;&
  $(( (option & option_4) >0 )) ) echo "- option_4 is set";;&
  $(( (option & option_5) >0 )) ) echo "- option_5 is set";;&
  $(( (option & option_6) >0 )) ) echo "- option_6 is set";;&
  $(( (option & option_7) >0 )) ) echo "- option_7 is set";;&
  $(( (option & option_8) >0 )) ) echo "- option_8 is set";;&
  $(( (option & option_9) >0 )) ) echo "- option_9 is set";;&
esac

echo ;
echo ;

echo "# to use it in an if statement:";
echo "  => if (((option&option_5)>0));";
if (((option&option_5)>0)); then
    echo "- option_5 is set"    
else
    echo "- option_5 is NOT set"
fi

echo ;
echo ;

declare -A releases=([token]=4)
declare -i MASK=5

echo "# Does 4 pass the mask 5 in the test construct?";
echo "  => if [[ $(( releases["token"] & $MASK )) -gt 0 ]];";
if [[ $(( releases["token"] & $MASK )) -gt 0 ]]; then
    echo YES
else
    echo NO
fi

echo ;
echo ;

echo "# or to use it just for conditional execution:";
echo "  => (((option&option_6)>0)) && do || dont";
(((option&option_6)>0)) \
&& echo "- option_6 is set" \
|| echo "- option_6 is NOT set"

)


结束

Exit 0


Answer 3:

在if语句:

if (((releases["token"] & $MASK) == 1)); then 
  echo YES
else 
  echo NO
fi


文章来源: How to use bitwise operators in if statements?