2

次の形式の数値のリストであるファイル(tmp1)があります。

4373610497
4416339969
4426498049
4435738625

ここでの各 64 ビット数値は、実際には複数の 16 ビット フィールドで構成されており、これらのフィールドには私が関心のある数値が含まれています。

例 (ここで重要な 48 ビットのみを表示) の場合:

4435738625 = 0000000000000001 0000100001100100 0000000000000001

そして、私が欲しい数字は次のとおりです。

a= 0000000000000001 = 1
b= 0000100001100100 = 2148
c= 0000000000000001 = 1

これは私が現在これを行うために使用しているコードですが、非常に遅いです。入力ファイルには 50 万行から 100 万行が含まれているため、これをより高速または効率的に行う方法を探しています。

while read line; do
  a=$((((line >> 32)) & 65535));
  b=$((((line >> 16)) & 65535));
  c=$((line & 65535));
  printf "$a $b $c\n" >>tmp2
done <tmp1

これを FreeBSD マシンで実行する必要があるため、gawk を使用できません。そして awk はビット単位の操作を許可していないようです。

4

3 に答える 3

3

解決策があり、ニーズに合います。しかし、それがあなたのものよりも速く動作するかどうかはわかりません。テストできます。

ここでは、あなたの例で 1 つの数値でテストするだけです。ループでラップできます。

kent$  printf "%064s\n" "$(bc <<< "obase=2;4435738625")"|sed -r 's/.{16}/ibase=2;&\n/g'|bc
1
2148
1
于 2013-10-16T13:53:35.863 に答える
2

そのためにビット操作は本当に必要ありません。例えば:

awk '{val = $1;
      c = val%65536; val = (val-c)/65536;
      b = val%65536; val = (val-b)/65536;
      a = val%65536;
      print a, b, c}'

ただし、awk 値は 64 ビット整数ではありません。これらは double であり、53 ビットの精度しかありません。そのため、どの数値も 9007199254740992 (2 53 ) を超えない場合にのみ機能します。

bcやなどの別のツールの使用を検討することもできますpython。GNU がbc利用できる場合 (BSD システムでも可能です)、次の非常によく似たプログラムが動作するはずです。

bc <(echo 'define s(val) {
             c = val%65536; val = (val-c)/65536
             b = val%65536; val = (val-b)/65536
             a = val%65536;
             print a," ",b," ",c,"\n";
           }
           while(1){v=read(); if (v==0) break; v=s(v);}') \
   < datafile

よく注意してください: bcread 関数はファイルの終わりをチェックしないので、ある種の明示的なターミネータを入れる必要があります。0上記のスクリプトで使用しましたが、それはあなたのケースでは有効な入力かもしれません。-1または他の特別な値に変更したい場合があります。とにかく、データファイルが実際にその値で終了していることを確認してください。

于 2013-10-16T15:46:39.610 に答える
0

set で使用bcobase、その文書化された動作:

基数が 16 を超える場合、bc は複数文字数字方式を使用して数値を出力します。基数が大きい場合は基数が 10 の数値として出力されます。複数文字の数字はスペースで区切られます。

$ bc -q <(echo "obase=65536") tmp1 <(echo "halt")
00001 01200 00001
00001 01852 00001
00001 02007 00001
00001 02148 00001

awk出力を少し調整する必要がある場合、たとえば先頭のゼロを削除するか、可変数の列を処理する必要がある場合は、それをパイプします (≥ 2 48の場合は 4 列、≥ 2 32の場合は 3列など):

| nawk '{printf("%i %i %i\n",(NF>2)?$(NF-2):0,(NF>1)?$(NF-1):0,$NF)}'

<(echo ...)パーツを使用bcすると、出力をファイルとして読み取ることができます。これechoは、これらの行をすべての入力ファイルの先頭と末尾に追加するための簡単な代替手段です。

于 2013-10-17T14:48:27.127 に答える