I'm curious about what exactly the following comparison does, in as much detail as possible, especially relating to the 0x2
and the &
characters and what exact开发者_高级运维ly they do,
if [ $((${nValid} & 0x1)) -eq 1 ]; then
#...snip...
fi
if [ $((${nValid} & 0x2)) -eq 2 ]; then
#...snip...
fi
& is the bitwise AND operator. So you are asking to do a bitwise and between 0x1 and the value that ${nVAlid} is returning.
For more information on bitwise operations look here.
A shell script interprets a number as decimal (base 10), unless that number has a special prefix or notation. A number preceded by a 0 is octal (base 8). A number preceded by 0x is hexadecimal (base 16). A number with an embedded # evaluates as BASE#NUMBER (with range and notational restrictions).
So, in [ $((${nValid} & 0x1)) -eq 1 ]
, $nValid
is anded with 0x1
and compared with decimal 1
. Similarly the second comparison too.
Read this and this for detailed info.
It's testing nValid on a per-bit basis.
The bitwise AND
operator (&
) means that bit-by-bit, the operator will do an AND
comparison. So, if nValid is a byte (8 bit) value, then look at the operation in binary:
nValue & 0b00000001
If nValue is 42, then the operation would look like this
(nValue = 0b00101010) & 0b00000001 => 0b00000000 // (does not have the last bit set)
(nValue & 0b00000001) == 0b00000001 // false
and for the 2nd (nValid & 0x2
)
(nValue = 0b00101010) & 0b00000010 => 0b00000010 // (has the 2nd-to-last bit set)
(nValue & 0b00000010) == 0b00000010 // true
This is useful for testing flags within variables; usually you use the AND
to check for flags by isolating bits and the OR
to combine flags.
0b00001000 | 0b00000010 | 0b00000001 => 0b00001011
0x1
and 0x2
are the hexadecimal notations for 1 and 2. The &
is the bitwise AND operator. What these lines do is test the value in nValid whether the least significant bit (0x1) and second least significant bit (0x2) are set.
The scheme goes like this (C notation):
if (val & (1 << bitNumber) == (1 << bitNumber)) {
// The bit at position bitNumber (from least to most significant digit) is set
}
The <<
is the left bitshift operator. 1 << 0 == 1
, 1 << 1 == 2
, 1 << 2 == 4
, ...
So for better readability the lines should be more like:
if [ $((${nValid} & X)) -eq X ]; then
where X is a power of 2 (instead of mixing hexadecimal and decimal notation).
That could be rewritten as:
if (( nValid & 2#00000001 )); then
#...snip...
fi
if (( nValid & 2#00000010 )); then
#...snip...
fi
with the number of binary digits chosen to be most appropriate for the context. It's not necessary to test for equality if you're only checking one bit*. You could still use the hex representation if it makes more sense. The braces and dollar sign aren't necessary in this context.
You might want to use constants with meaningful names instead of hard-coded values:
declare -r FOO=$((2#00000001))
declare -r BAR=$((2#00000010))
if (( nValid & FOO )); then
#...snip...
fi
if (( nValid & BAR )); then
#...snip...
fi
* You will need to test for equality if you're testing multiple bits at the same time:
if (( (nValid & (FOO | BAR)) == (FOO | BAR) )); then
#...snip...
fi
You will need the extra parentheses since ==
has a higher precedence than the bitwise operators.
Clearing and setting bits in Bash:
(( var |= FOO )) # set the bits in FOO into var
(( var &= ~BAR )) # clear the bits in BAR from var
精彩评论