开发者

How to make calculations on hexadecimal numbers with awk?

I have a file containing a list of hexadecimal numbers, as 0x12345678 one per line.

I want to make a calculation on them. For this, I thought of using awk. But if printing an hexadecimal number with awk is easy with the printf f开发者_如何转开发unction, I haven't find a way to interpret the hexadecimal input other than as text (or 0, conversion to integer stops on the x).

awk '{ print $1; }'                     // 0x12345678
awk '{ printf("%x\n", $1)}'             // 0
awk '{ printf("%x\n", $1+1)}'           // 1                 // DarkDust answer
awk '{ printf("%s: %x\n", $1, $1)}'     // 0x12345678: 0

Is it possible to print, e.g. the value +1?

awk '{ printf(%x\n", ??????)}'          // 0x12345679

Edit: One liners on other languages welcomed! (if reasonable length ;-) )


In the original nawk and mawk implementations the hexadecimal (and octal) numbers are recognised. gawk (which I guess you are using) has the feature/bug of not doing this. It has a command line switch to get the behaviour you want: --non-decimal-data.

echo 0x12345678 | mawk '{ printf "%s: %x\n", $1, $1 }'
0x12345678: 12345678

echo 0x12345678 | gawk '{ printf "%s: %x\n", $1, $1 }'
0x12345678: 0

echo 0x12345678 | gawk --non-decimal-data '{ printf "%s: %x\n", $1, $1 }'
0x12345678: 12345678


gawk has the strtonum function:

% echo 0x12345678 | gawk '{ printf "%s: %x - %x\n", $1, $1, strtonum($1) }'
0x12345678: 0 - 12345678


Maybe you don't need awk at all, as string/number conversion is hairy. Bash versions 3 and 4 are very powerful. It is often simpler, clearer and more portable to stay in Bash, and maybe use grep and cut etc.

For example, in Bash hexadecimal numbers are converted naturally:

$ printf "%d" 0xDeadBeef
3735928559
$ x='0xE'; printf "%d %d %d" $x "$x" $((x + 1))
14 14 15

Hope this helps.


here are the different combinations of their behaviors :

using this command

'BEGIN { print 0xFACECAFEFEED^2, -0xFEEDCAFEFACEBEEFDEADFACEFEED7,
 -"0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE" }'

gawk -e (GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1))

  76046928626116243263483543552 -82729151009071240233065844435845120 0

gawk -P -e

  00 0
  -21377898657284658184582485743897013874545437686817998522919218577408

gawk -c -e

  00 0 0 

gawk -n -e

  76046928626116243263483543552 -82729151009071240233065844435845120
  -21377898657284658184582485743897013874545437686817998522919218577408

gawk -S -e

  76046928626116243263483543552 -82729151009071240233065844435845120 0

gawk -M

76046928626116245157029816169 -82729151009071239007500567260950231 0

gawk -l mpfr

  76046928626116243263483543552 -82729151009071240233065844435845120 0

nawk (macos awk version 20200816)

 00 0 -2.13778986572846581845824857439e+67

mawk 1.3.4

 00 0 -2.13779e+67

mawk2-beta (1.9.9.6)

 00 0 0

In fact, if one has a custom awk-script library that works across multiple awk variants, but also wanna take their idiosyncrasies into account, one approach would be use the difference in outputs here to auto-flag, with relatively few combinations left where one needs a tie-breaker.


*** this is only an extension of my comment following schot's response, strictly for proper formatting purposes.

echo FACEBEACEBEFACEEFFFACEEEFFFACEFACFACEB | 
    mawk '{ printf("%s\n%.f\n%x\n%.f\n",$0,$0,"0x"$0,"0x"$0) }'

FACEBEACEBEFACEEFFFACEEEFFFACEFACFACEB
0
ffffffff
5593196314036579851314282024549245003233230848

5593196314036579608368524797845507287542639851 #exact
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜