Cómo convertir una columna de hexadecimal a dec en gawk, strtonum en gawk da resultados erróneos

Cómo convertir una columna de hexadecimal a dec en gawk, strtonum en gawk da resultados erróneos

Estoy intentando crear un script en una base de datos desde una secuencia de red. La transmisión de red después de ser fuertemente sed arroja un archivo de tres columnas que se parece a este llamado file.db

123.123.123.123, nombre de computadora, 110000103e21cc4

123.123.123.124,computadora2,11000010416200f

123.123.123.1, computadora3,110000106eb3f43

Intenté usar este comando gawk sin éxito

gawk 'BEGIN {FS=OFS=","} {print $1,$2,strtonum("0x"$3)}' file.db

el resultado de lo anterior se ve así

123.123.123.123, nombre de computadora, 76561198025415874

123.123.123.124,computadora2,76561198028824592

123.123.123.1,computadora3,76561198076346171

sin embargo, la salida debería convertirse a esto

123.123.123.123, nombre de computadora, 76561198025415876

123.123.123.124,computadora2,76561198028824591

123.123.123.1,computadora3,76561198076346179

la salida siempre está desviada en una cantidad menor, por lo que supongo que alguna biblioteca en el sistema no es correcta... Por cierto, este es un sistema integrado que se está ejecutando y sé que puede convertir porque lo he hecho con bc, printf, etcétera etcétera

¿Cómo puedo hacer que esto funcione?

Respuesta1

Almacena internamente gawkel valor convertido en un punto flotante de doble precisión, por lo que la pequeña discrepancia es simplemente un error de redondeo heredado de cualquier valor de punto flotante. Para obtener resultados precisos, gawkes necesario subcontratar el manejo de números a otros comandos que admitan números de precisión arbitraria, como bc.

Sin embargo, con la sintaxis actual gawkes imposible realizar un análisis complejo de la línea de comandos del shell dentro de gawk, por lo que primero necesitaría un asistente de script del shell. Pongámosle un nombre bc.sh:

#!/bin/bash
echo -e "ibase=16\n$1" | bc -q

Este script introduce ibase=16el primer argumento (número hexadecimal) en bc, de modo que bcgenera el número decimal correspondiente. Entonces gawkse llamaría de esta manera:

gawk 'BEGIN {FS=OFS=","} { "./bc.sh " toupper($3) | getline b; print $1,$2,b}' file.db

Esto le indica gawkque llame al script de shell con $3 en mayúsculas ( bcno admite valores hexadecimales en minúsculas), almacene el resultado en buna variable e imprima todos los argumentos de una sola vez.

Tenga en cuenta que ./bc.shdebe tener algo de espacio añadido entre comillas dobles; de lo contrario, intentará ejecutar un archivo inexistente como ./bc.sh110000103E21CC4.

Respuesta2

Miro hacia atrás en esto y la forma en que terminé haciendo esto es

hacer un script bash como el llamado convert12345678.sh

#!/opt/bin/bash
(echo -e "ibase=16\nobase=0A" ; echo $1 | tr 'a-z' 'A-Z') | bc | tr "\n" " " | sed 's/\ //g'

y luego, mirando boquiabierto por lo que necesitaba, dije como en la operación (he modificado mucho ese programa desde entonces) era algo como esto, y transmití este programa, pero lo demostraré desde un archivo.

gawk -F, '{printf("%s,%s,",$1,$2)};{system("/files/convert12345678 "$3)};{printf("\n")}' file.db

Lo hice de esta manera eliminando la nueva línea en el script bash porque, honestamente, la moví después, es decir, la ubicación de ejecución del script, de esta manera no tendría la nueva línea intercalada en la salida inmediatamente después de la conversión a menos que lo quisiera con imprimirf

información relacionada