Joh*_*ohn 4 shell awk numeric-data
当十六进制数字相对较小时,我可以使用
echo 0xFF| mawk '{ printf "%d\n", $1}'
Run Code Online (Sandbox Code Playgroud)
将十六进制转换为十进制。
当十六进制数很大时,mawk不再起作用,例如
echo 0x8110D248 | mawk '{ printf "%d\n", $1 }'
Run Code Online (Sandbox Code Playgroud)
输出2147483647(这是错误的,2147483647相当于0x7FFFFFFF)。
如何转换更大的数字?
我有很多数字(每行一个数字,超过10M)需要处理,例如:每个0xFF\n 0x1A\n 0x25\n. 如何让它在这种场合发挥作用?经过xargs?有没有更好的方法呢?xargs真的很慢。
用于任意大数字的更好命令是bc。这是执行转换的函数
hextodec() {\n local hex="${1#0x}"\n printf "ibase=16; %s\\n" "${hex^^}" | bc\n}\n\nhextodec 0x8110D248\n2165363272\nRun Code Online (Sandbox Code Playgroud)\n我在这里使用了一些看起来很奇怪的功能,它们在使用变量时操纵它们的值:
\n"${1#0x}"-"$1"正如您所期望的,这引用了函数的第一个参数。是#一个修饰符(man bash例如,请参阅 或读取POSIX),用于从值的前面删除以下表达式。例如,0xab12将返回为ab12"${hex^^}"- 此引用"$hex"但返回其值,其中字母字符映射为大写。(这是一个bash扩展,因此请读取man bash但不是 POSIX。)例如,12ab34将返回为12AB34在这两种情况下,{ \xe2\x80\xa6 }大括号将修饰符绑定到变量;"$hex^^"只会返回$hex变量的值,后跟两个向上箭头/插入符字符
您的问题来自于mawk内部使用带符号的 32 位整数,因此不能表示大于 2 31 -1 (即 2147483647)的整数。
要流式传输具有任意大小的十六进制数字的文件,请将每个文件转换为十进制:
{
echo 'ibase=16'
sed -e 'y/xabcdef/XABCDEF/' -e 's/^0X//'
} | bc
Run Code Online (Sandbox Code Playgroud)
首先发送ibase=16到bc,指示实用程序读取十六进制数字。thensed用于将十六进制字母转换为大写并删除0x文件中数字的任何前缀。我们这样做是因为需要没有前缀且带有大写字母的bc十六进制数字。0x
file给定一个包含内容的文件
0xFF
0x1A
0x25
0x7FFFFFFF
0x8110D248
0x8110D2487FFFFFFF
Run Code Online (Sandbox Code Playgroud)
...管道将输出
255
26
37
2147483647
2165363272
9300164439347036159
Run Code Online (Sandbox Code Playgroud)
您还可以将管道重写为通用流 shell 函数:
hex2dec () {
{ echo 'ibase=16'; sed -e 'y/xabcdef/XABCDEF/' -e 's/^0X//'; } | bc
}
hex2dec <file
# Or...
some-process-producing-data |
some-filter-extracting-hexadecimal-numbers |
hex2dec |
while IFS= read -r number
# use the decimal number in "$number" here.
done
Run Code Online (Sandbox Code Playgroud)