awk output into BC HexToDec calculation

随声附和 提交于 2019-12-23 02:01:43

问题


I am trying to combine awk and bc in order to create a bash function for quickly converting hex values into a proper format.

echo FFFFFF | VAR=$(awk '{print toupper($0)}') | "ibase=16; $((((($VAR - 5) / 100) - 1000)))" | bc

I am trying this but I cant seem to get the output of awk into the input of the bc argument.


回答1:


Although you try to do it with awk and bc, I give you the most convenient option here : printf. This allows you to easily convert between decimal, octal and hexadecimal.

[bash] % printf "%d" 0xFFFFFF    # hex2dec
16777215
[bash] % printf "%#O" 0xFFFFFF   # hex2oct
077777777
[bash] % printf "%d" 077777777   # oct2dec
16777215
[bash] % printf "%d" 077777777   # oct2hex
0xFFFFFF
[bash] % printf "%#x" 16777215   # dec2hex
0xFFFFFF
[bash] % printf "%#O" 16777215   # dec2oct
077777777

The extra character # asks printf to insert the prefix 0X for hexadecimal numbers, and 0 for octal numbers. If you add numbers in hexadecimal form, do not forget to add the prefix 0x to the number, and 0 for octal numbers.

Ofcourse bash has an option to do arithmatic operations.

man bash((expression)) The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression".

This allows you to do all your computations directly. Eg. you want 0xFFFFFF and subtract decimal 5 and divide by 100 (decimal) and subtract 1000 decimal, you have

[bash] % printf "%d" $(( (0xFFFFFF - 5)/100 - 1000 ))
166772

Or you can do it all hexadecimal ::

[bash] % printf "%d" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 ))
61439

If you now want to store such a number in a variable, you just do

[bash] % vardec=$( printf "%d" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )
[bash] % varhex=$( printf "%#x" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )
[bash] % varoct=$( printf "%#O" $(( (0xFFFFFF - 0x5)/0x100 - 0x1000 )) )

However, decimal is such a special case, that you can get rid of the printf:

[bash] % vardec=$(( (0xFFFFFF - 0x5)/0x100 - 0x1000 ))

The arithmetic evaluation system of bash allows you to write any number in any base (up to base 64), and convert it to decimal. Here I convert a base 3 number 3#1212 into the number 50.

[bash] % echo $(( 3#1212 ))
50

If you wan to use zsh, you can convert back to any other base :

[zsh] % echo $(( [##2]7 ))            # from base 10 to base 2
111
[zsh] % echo $(( [##5]3#1020101100 )) # from base 3 to base 5
1234321
[zsh] % echo $(( [##36]17#415C67A8 )) # from base 17 to base 36
ROFLOL



回答2:


try

 echo FFFFFF |
 awk '{printf "ibase=16\n(((((%s - 5) / 100) - 1000)))\n",toupper($1) ;}' |
 bc

(this can be onlined, be sure | is last char in line)

in original script

echo FFFFFF | VAR=$(awk '{print toupper($0)}') 
  • awk has no input, VAR in empty

    "ibase=16; $((((($VAR - 5) / 100) - 1000)))"
    
  • "ibase=... " is a command, this isn't what you want, and it output nothing (save an error).

more complex formulae

VAR=$(echo FFFFFF | tr [:lower:] [:upper:])
VAR2=..
VARx=...
bc <<EOF
ibase=16
((($VAR - 5) / $VAR2) - $VARx)
EOF

where

  • bc <<EOF is called a heredoc variable will get sbustitued on run.



回答3:


You didn't provide any sample input or expected output but is this what you're trying to do?

$ echo FFFFFF | awk '{print strtonum("0x"$0)}'
16777215

$  echo FFFFFF | awk '{print ((strtonum("0x"$0) - 5) / 100) - 1000}'
166772

The above uses GNU awk for strtonum() to convert non-decimal strings to numeric values and case doesn't matter:

$  echo ffffff | awk '{print ((strtonum("0x"$0) - 5) / 100) - 1000}'
166772

or maybe your "100", etc. are intended to be hex too?

$ echo FFFFFF | awk '{print ((strtonum("0x"$0) - strtonum("0x5")) / strtonum("0x100")) - strtonum("0x1000")}'
61440

Note that the result of the calculation is actually a float and so rounding applies above when printing it as an integer:

$ echo FFFFFF | awk '{printf "%f\n", ((strtonum("0x"$0) - strtonum("0x5")) / strtonum("0x100")) - strtonum("0x1000")}'
61439.976562

P.S. I started out using the gawk-only -n option for this but that should actually be avoided in favor of strtonum(), see https://www.gnu.org/software/gawk/manual/gawk.html#Nondecimal-Data.



来源:https://stackoverflow.com/questions/48748346/awk-output-into-bc-hextodec-calculation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!