问题
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 is0
; otherwise the return status is1
. This is exactly equivalent tolet "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