ネットワーク ストリームからデータベースをスクリプト化しようとしています。ネットワーク ストリームは、大量の sed を実行した後、次のような 3 列のファイル (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
、最初の引数 (16 進数) を に入力しbc
、bc
対応する 10 進数を出力します。次に、 はgawk
次のように呼び出されます。
gawk 'BEGIN {FS=OFS=","} { "./bc.sh " toupper($3) | getline b; print $1,$2,b}' file.db
これは、gawk
大文字の $3 (bc
小文字の 16 進値はサポートされていません) を使用してシェル スクリプトを呼び出し、結果を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'
そして、私がOPで言ったように、gawkで必要なことはすべて(それ以来そのプログラムを大幅に変更しました)次のようにしました。このプログラムをパイプしましたが、ファイルからデモンストレーションします。
gawk -F, '{printf("%s,%s,",$1,$2)};{system("/files/convert12345678 "$3)};{printf("\n")}' file.db
私は、bash スクリプトの改行を削除してこの方法を実行しました。なぜなら、後でスクリプトの実行場所を移動したからです。そのため、この方法では、printf で変更したい場合を除き、変換直後に出力に改行が挿入されることはありません。