Я пытаюсь написать скрипт базы данных из сетевого потока. Сетевой поток после интенсивного sed'а выдает файл с тремя столбцами, который выглядит примерно так, называется file.db
123.123.123.123,имя компьютера,110000103e21cc4
123.123.123.124,компьютер2,11000010416200f
123.123.123.1,компьютер3,110000106eb3f43
Я пытался использовать эту команду gawk, но безуспешно.
gawk 'BEGIN {FS=OFS=","} {print $1,$2,strtonum("0x"$3)}' file.db
вывод из вышесказанного выглядит так
123.123.123.123,имя компьютера,76561198025415874
123.123.123.124,компьютер2,76561198028824592
123.123.123.1,компьютер3,76561198076346171
однако вывод должен преобразоваться в это
123.123.123.123,имя компьютера,76561198025415876
123.123.123.124,компьютер2,76561198028824591
123.123.123.1,компьютер3,76561198076346179
вывод всегда немного отличается, поэтому я предполагаю, что какая-то библиотека в системе некорректна... Кстати, это встроенная система, на которой она работает, и я знаю, что она может преобразовывать, потому что я делал это с помощью bc, printf и т. д. и т. п.
Как мне это сделать?
решение1
Внутри себя 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
.
решение2
Оглядываясь назад, я понимаю, что в итоге я пришел к такому выводу:
создание 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 для всего, что мне было нужно, скажем, в op (я сильно изменил эту программу с тех пор) было что-то вроде этого, и я передал эту программу, но я продемонстрирую это из файла
gawk -F, '{printf("%s,%s,",$1,$2)};{system("/files/convert12345678 "$3)};{printf("\n")}' file.db
Я сделал это таким образом, удалив новую строку в скрипте bash, потому что, честно говоря, я переместил ее позже, то есть место выполнения скрипта, так что таким образом я не буду вставлять новую строку в вывод сразу после преобразования, если только я не захочу этого с помощью printf.