Как преобразовать столбец hex в dec в gawk, strtonum в gawk дает ошибочные результаты

1

Я пытаюсь сценарий базы данных из сетевого потока. Поток сети после того, как он был в большой степени sed, удаляет файл из трех столбцов, который выглядит примерно так: file.db

123.123.123.123, имя компьютера, 110000103e21cc4

123.123.123.124, computer2,11000010416200f

123.123.123.1, computer3,110000106eb3f43

я пытался использовать эту команду gawk безрезультатно

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

вывод из вышеперечисленного выглядит следующим образом

123.123.123.123, имя компьютера, 76561198025415874

123.123.123.124, computer2,76561198028824592

123.123.123.1, computer3,76561198076346171

однако вывод должен преобразовываться в это

123.123.123.123, имя компьютера, 76561198025415876

123.123.123.124, computer2,76561198028824591

123.123.123.1, computer3,76561198076346179

вывод всегда отключен на небольшую величину, поэтому я предполагаю, что какая-то библиотека в системе неверна ... кстати, это встроенная система, на которой она работает, и я знаю, что она может конвертироваться, потому что я сделал это с помощью bc, printf, и т. д.

Как я могу сделать эту работу

Крис
источник

Ответы:

0

Внутренне gawkсохраняет преобразованное значение с плавающей запятой двойной точности, поэтому небольшое расхождение просто является ошибкой округления, наследуемой для любого значения с плавающей запятой. Чтобы получить точный результат, gawkнеобходимо обработать исходящие числа другим командам, которые поддерживают числа с произвольной точностью, например bc.

Однако с текущим gawkсинтаксисом невозможно выполнить сложный анализ командной строки оболочки в gawk, поэтому сначала потребуется помощник сценария оболочки. Давайте назовем это bc.sh:

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

Этот скрипт передает ibase=16и первый аргумент (шестнадцатеричное число) bc, чтобы bcвывести соответствующее десятичное число. Тогда gawkбудет называться так:

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

Это говорит gawkо необходимости вызова сценария оболочки с $ 3 в верхнем bcрегистре ( не поддерживает шестнадцатеричное значение в нижнем регистре), сохранения результата в bпеременной и печати всех аргументов за один раз.

Помните, что ./bc.shв двойных кавычках должно быть добавлено некоторое пространство, в противном случае он попытается выполнить несуществующий файл, такой как ./bc.sh110000103E21CC4.

Абель Чунг
источник
это работает, если я делаю предыдущий код и обрезку столбца три, а затем использую вставку, но я бы предпочел что-то, что можно сделать с помощью awk. Это потому, что если есть что-то, что нарушает формирование файла db, то есть дополнительная строка или более, которые не были проанализированы с помощью sed, это вызывает огромные проблемы с вставкой. помните, что это входной поток в реальном времени от ngrep, и хотя сценарий sed, который не был опубликован, довольно хорошо отточен, некоторые вещи могут проскальзывать ... вывод этого раздела сценария комбинируется с большей базой данных, и целостность обязательно
Крис
@Chris Использование awk возможно, но с учетом его ограничения числовых значений необходимо использовать какой-то внешний фильтр. Хотя awkможно вызывать внешние программы, хакерский способ решения этой проблемы заставляет меня поверить, что написание сценария оболочки (с использованием cutи bc) лучше подходит для этой задачи, чем в awkодиночку. В любом случае, я изменю решение в соответствии с вашими требованиями, и вам решать, как это сделать.
Абель Чунг
0

Я оглядываюсь назад на это, и то, как я это сделал,

создание bash-скрипта вроде так называемого convert12345678.sh

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

и затем в gawk для того, что мне нужно было сказать, как в операторе (я сильно изменил эту программу с тех пор) было что-то вроде этого, и я передал эту программу, но я продемонстрирую из файла

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

я сделал это таким образом, удалив новую строку в bash-скрипте, потому что, честно говоря, я переместил ее потом, размещение выполнения скрипта, то есть, таким образом, я бы не вставлял символ новой строки в вывод сразу после преобразования, если я не хотел, чтобы Printf

Крис
источник