我想在Bash或其他shell中反转一个十六进制数。
比如,我要反转十六进制数4BF8E,答案应该是71FD2,即按位反转。
echo 4BF8E | rev | tr '0123456789ABCDEF' '084C2A6E195D3B7F'
解释:
[g/n/m]awk 'BEGIN {
____=index(___="bits::[%.f]"\
(_="\n")"%s"(_)_,".")
__=index("_"(_="0|1|"),_)
do { gsub(/[^|]+[|]/,"0&1&",_)
printf(___,__,_)
} while(++__<____) }'
它将为所有8位生成按顺序排序的位反射位字符串,输出如下:
bits::[2]
00|10|01|11|
bits::[3]
000|100|010|110|001|101|011|111|…
bits::[4]
0000|1000|0100|1100|0010|1010|0110|1110|0001|1001|0101|1101|0011|1011|0111|1111|
bits::[5]
00000|10000|01000|11000|00100|10100|01100|11100|00…
bits::[6]…
000000|100000|010000|110000|001000|101000|011000|1…
bits::[7]
0000000|1000000|0100000|1100000|0010000|1010000|01…
bits::[8]
00000000|10000000|01000000|11000000|00100000|10100…
只需执行7次do-while循环,您就可以获得所有256字节的反射,按其字节序值预先排序。
在4位级别上,这些位字符串确实对应于十六进制等效项084C 2A6E-195D-3B7F
[g/n/m]awk 'mawk2 '
BEGIN { ___=" bits : %2.f | combos :"\
" %8.f | tot-len : %10.f\n"
_="0|"(____="1")"|"
# specify max-bit-level
# fail safe default to 8
#
____=(____+=int( 24 ))<(__=3)?__*__:____;
__=index("_"_,_)
do {
gsub(/[^|]+[|]/,"0&1&",_)
printf(___,__,(_____=\
length(_))/(++__),_____)
} while (__<____) }'
bits : 2 | combos : 4 | tot-len : 12
bits : 3 | combos : 8 | tot-len : 32
bits : 4 | combos : 16 | tot-len : 80
bits : 5 | combos : 32 | tot-len : 192
bits : 6 | combos : 64 | tot-len : 448
bits : 7 | combos : 128 | tot-len : 1024
bits : 8 | combos : 256 | tot-len : 2304
bits : 9 | combos : 512 | tot-len : 5120
bits : 10 | combos : 1024 | tot-len : 11264
bits : 11 | combos : 2048 | tot-len : 24576
bits : 12 | combos : 4096 | tot-len : 53248
bits : 13 | combos : 8192 | tot-len : 114688
bits : 14 | combos : 16384 | tot-len : 245760
bits : 15 | combos : 32768 | tot-len : 524288
bits : 16 | combos : 65536 | tot-len : 1114112
bits : 17 | combos : 131072 | tot-len : 2359296
bits : 18 | combos : 262144 | tot-len : 4980736
bits : 19 | combos : 524288 | tot-len : 10485760
bits : 20 | combos : 1048576 | tot-len : 22020096
bits : 21 | combos : 2097152 | tot-len : 46137344
bits : 22 | combos : 4194304 | tot-len : 96468992
bits : 23 | combos : 8388608 | tot-len : 201326592
bits : 24 | combos : 16777216 | tot-len : 419430400
就速度而言,
如果您想尝试更高位字符串组合级别,请确保您的系统能够处理:
bits : 25 | combos : 33554432 | tot-len : 872415232
bits : 26 | combos : 67108864 | tot-len : 1811939328
bits : 27 | combos : 134217728 | tot-len : 3758096384
bits : 28 | combos : 268435456 | tot-len : 7784628224
bits : 29 | combos : 536870912 | tot-len : 16106127360
bits : 30 | combos : 1073741824 | tot-len : 33285996544
bits : 31 | combos : 2147483648 | tot-len : 68719476736
mawk2 354.61秒用户时间 44.08秒系统时间 88% cpu7:29.79 总共耗时
我不敢超过31位组合。那已经有
我的电脑花了约7.5分钟才完成这个任务。
def bin(a):
"""
For python 2 this is needed to convert a value to a bitwise string
in python 3 there is already a bin built in
"""
s=''
t={'0':'0000', '1':'0001', '2':'0010', '3':'0011',
'4':'0100', '5':'0101', '6':'0110', '7':'0111',
'8':'1000', '9':'1001', 'a':'1010', 'b':'1011',
'c':'1100', 'd':'1101', 'e':'1110', 'f':'1111',
}
for c in hex(a)[2:]:
s+=t[c]
return s
def binrevers(hex):
IntForm = int(hex, 16)
BinForm = bin(IntForm)
rBin = BinForm[::-1]
Val = int(rBin, 2)
return "%x" % Val
尝试交互式操作:
>>> binrevers("4BF8E")
'71fd2'
>>>
if __name__ == "__main__":
import sys
for i in sys.argv[1:]:
print i, binrevers(i)
我认为帮助可视化“比特反射”的一种方法是将其显示在所有256字节比特反射的网格中。
008040C020A060E 0109050D030B070F0 088848C828A868E 8189858D838B878F8
048444C424A464E 4149454D434B474F4 0C8C4CCC2CAC6CE C1C9C5CDC3CBC7CFC
028242C222A262E 2129252D232B272F2 0A8A4ACA2AAA6AE A1A9A5ADA3ABA7AFA
068646C626A666E 6169656D636B676
F6
0E8E4ECE2EAE6EE E1E9E5EDE3EBE7EFE
.
018141C121A161E 1119151D131B171F1
09
8949C929A969E 9199959D939B979F9
058545C525A565E 5159555D535B575F5 0D8D4DCD2DAD6DE D1D9D5DDD3DBD7DFD
038343C323A363E 3139353D333B373F3 0B8B4BCB2BAB6BE B1B9B5BDB3BBB7BFB
078747C727A767E 7179757D737B777F7 0F8F4FCF2FAF6FE F1F9F5FDF3FBF7FFF
对于每个字节,其对角线镜像的版本将是位反转的版本,如粗体示例所示:xF6
和x09
084C 2A6E :: 1st 1/2 - evens
195D 3B7F :: 2nd 1/2 - odds
如果你想使用正则表达式从头开始重新创建参考字符串,而不是实际计算每个比特位,那么在你想要添加2个以上比特的每一层中使用这个...
00 & 10 & 01 & 11 & # without the spaces
……这意味着,如果你想在没有访问原生的 按位异或
操作的情况下计算它们,四进制
是最有帮助的,因为只有中间对 1 | 2
交换,而外部对 0 | 3
保持不变。
使用以下算法:
00001011
反转后变成了11010000
,而取反后则是11110100
- 这是两个完全不同的操作。反转位在快速傅里叶变换中非常有用(尽管为什么要在 bash 中编写 FFT 呢?),或者用于解码以不同顺序序列化为十六进制字符串的位数组。 - SF.hex_nr=0x2C8B; hex_len=$(( ${#hex_nr} - 2 )); inverted=$(printf '%X' "$(( ~ hex_nr ))"); trunc_inverted=${inverted: -hex_len}; echo $trunc_inverted
- Matthias Braun