如何在 gawk 中將十六進制列轉換為十進制,gawk 中的 strtonum 給出錯誤結果

如何在 gawk 中將十六進制列轉換為十進制,gawk 中的 strtonum 給出錯誤結果

我正在嘗試從網路流編寫資料庫腳本。經過大量 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 中進行複雜的 shell 命令列解析,因此首先需要一個 shell 腳本助手。讓我們命名它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 呼叫 shell 腳本(bc不支援小寫的十六進位值),將結果儲存到b變數中,並一次列印所有參數。

請注意,./bc.sh雙引號內必須附加一些空格,否則它將嘗試執行不存在的文件,例如./bc.sh110000103E21CC4.

答案2

我回顧這件事,我最終這樣做的方式是

製作一個名為convert12345678.sh的bash腳本

#!/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腳本中的新行,因為老實說,我後來移動了它,即腳本執行位置,所以這樣我就不會在轉換後立即將換行符插入到輸出中,除非我希望它與列印函數

相關內容