使用“mawk”将十六进制转换为十进制超出范围

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真的很慢。

roa*_*ima 6

用于任意大数字的更好命令是bc。这是执行转换的函数

\n
hextodec() {\n    local hex="${1#0x}"\n    printf "ibase=16; %s\\n" "${hex^^}" | bc\n}\n\nhextodec 0x8110D248\n2165363272\n
Run Code Online (Sandbox Code Playgroud)\n

我在这里使用了一些看起来很奇怪的功能,它们在使用变量时操纵它们的值:

\n
    \n
  • "${1#0x}"-"$1"正如您所期望的,这引用了函数的第一个参数。是#一个修饰符(man bash例如,请参阅 或读取POSIX),用于从值的前面删除以下表达式。例如,0xab12将返回为ab12
  • \n
  • "${hex^^}"- 此引用"$hex"但返回其值,其中字母字符映射为大写。(这是一个bash扩展,因此请读取man bash但不是 POSIX。)例如,12ab34将返回为12AB34
  • \n
\n

在这两种情况下,{ \xe2\x80\xa6 }大括号将修饰符绑定到变量;"$hex^^"只会返回$hex变量的值,后跟两个向上箭头/插入符字符

\n


Kus*_*nda 5

您的问题来自于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=16bc,指示实用程序读取十六进制数字。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)