Jak przekonwertować kolumnę hex na dec w gawk, strtonum w gawk daje błędne wyniki

1

Próbuję skrypty bazy danych ze strumienia sieciowego. Strumień sieci po silnym seddzie upuszcza plik z trzema kolumnami, który wygląda mniej więcej tak zwany file.db

123.123.123.123, nazwa komputera, 110000103e21cc4

123.123.123.124, komputer2,11000010416200f

123.123.123.1, komputer3,110000106eb3f43

próbowałem użyć tego polecenia gawk bezskutecznie

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

wynik z powyższego wygląda następująco

123.123.123.123, nazwa komputera, 76561198025415874

123.123.123.124, komputer2,76561198028824592

123.123.123.1, komputer3,76561198076346171

jednak dane wyjściowe powinny zostać przekonwertowane na to

123.123.123.123, nazwa komputera, 76561198025415876

123.123.123.124, komputer2,76561198028824591

123.123.123.1, komputer3,76561198076346179

dane wyjściowe są zawsze wyłączone w niewielkiej ilości, więc zakładam, że część biblioteki w systemie jest niepoprawna ... btw to jest osadzony system, na którym działa i wiem, że może konwertować, ponieważ zrobiłem to z bc, printf, itd itd

Jak mogę to zrobić?

Chris
źródło

Odpowiedzi:

0

Wewnętrznie gawkprzechowuje przekonwertowaną wartość na zmiennoprzecinkową podwójną precyzję, więc mała rozbieżność jest po prostu błędem zaokrąglenia odziedziczonym do dowolnej wartości zmiennoprzecinkowej. Aby uzyskać dokładny wynik, gawkkonieczne jest przeniesienie obsługi numerów na inne polecenia obsługujące dowolne precyzyjne liczby, takie jak bc.

Jednak przy obecnej gawkskładni niemożliwe jest wykonywanie złożonego parsowania linii poleceń powłoki w gawk, dlatego najpierw potrzebowałby pomocnika skryptu powłoki. Nazwijmy to bc.sh:

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

Skrypt podaje ibase=16i pierwszy argument (liczbę szesnastkową) do bc, dzięki czemu bcwypisuje odpowiednią liczbę dziesiętną. Wtedy gawknazwano by tak:

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

Mówi to, gawkaby wywołać skrypt powłoki z wielkimi bcliterami 3 $ ( nie obsługuje małych wartości szesnastkowych), zapisać wynik w bzmiennej i wydrukować wszystkie argumenty za jednym razem.

Uważaj, ./bc.shaby wewnątrz podwójnego cudzysłowu było dołączone miejsce, w przeciwnym razie nastąpi próba wykonania nieistniejącego pliku, np ./bc.sh110000103E21CC4.

Abel Cheung
źródło
działa to, jeśli zrobię poprzedni kod i przycięcie kolumny trzeciej, a następnie użyję wklejania, ale wolałbym coś, co można zrobić za pomocą awk. Wynika to z faktu, że jeśli coś zakłóca tworzenie pliku db, tj. Dodatkowa linia lub więcej, która nie została przeanalizowana za pomocą sed, powoduje to ogromne problemy z wklejaniem. pamiętajcie, że jest to transmisja na żywo z ngrep i chociaż nie opublikowany skrypt sed został całkiem dobrze dopracowany, niektóre rzeczy mogą się przedostać ... wynik tej sekcji skryptu jest połączony z większą bazą danych, a integralność jest obowiązkowy
Chris
@Chris Korzystanie z awk jest możliwe, ale biorąc pod uwagę jego ograniczenie wartości liczbowej, należy zastosować pewien rodzaj zewnętrznego filtra. Chociaż awkmożna wywoływać programy zewnętrzne, hacky sposób rozwiązania tego problemu prowadzi mnie do przekonania, że ​​napisanie skryptu powłoki (użycie cuti bc) lepiej nadaje się do tego zadania niż awksamemu. W każdym razie zmodyfikuję rozwiązanie, aby pasowało do twoich wymagań, od ciebie zależy, jak to zrobić.
Abel Cheung
0

Patrzę wstecz na to i sposób, w jaki skończyłem to robić

tworzenie skryptu bash, takiego jak tzw. convert12345678.sh

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

a potem w gawk za wszystko, co potrzebowałem powiedzieć, jak w op (mocno zmodyfikowałem ten program od tego czasu), było coś takiego: i sipowałem ten program, ale zademonstruję z pliku

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

Zrobiłem to w ten sposób, usuwając nową linię w skrypcie bash, ponieważ szczerze przesunąłem ją później, umieszczając wykonanie skryptu, czyli w ten sposób nie chciałbym, aby nowa linia była wstawiana do wyniku natychmiast po konwersji, chyba że chciałem printf

Chris
źródło