2013-10-16 61 views
2

我有一個文件(TMP1),這是在以下格式號碼的列表:什麼是使用bash,awk或sed在文件中移位和掩碼每個數字的最快方法?

4373610497 
4416339969 
4426498049 
4435738625 

這裏的每64位的數字實際上是由它有我的數字多16位字段感興趣的

對於EG(和只顯示了48位,在這裏重要):

4435738625 = 0000000000000001 0000100001100100 0000000000000001 

而且我想數字是:

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

這是我現在用來做這件事的代碼 - 但它很痛苦地慢。輸入文件包含500K到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似乎不允許按位操作。

+0

試試這個'awk'腳本:http://www.cs.ucsb.edu/~sherwood/awk/decimal2binary.awk.txt –

+0

看到這個:http://stackoverflow.com/questions/5488551/how- to-unpack-64-bit-unsigned-long-in-64-bit-perl – michael501

回答

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位整數;他們是雙打的,只有53比特的精度。因此,只有當您的號碼都不超過9007199254740992(2 )時纔會有效。

您可能會考慮使用其他工具,如bcpython。如果你有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 

注意哦:在bc讀取功能不檢查文件結束,所以你需要放置某種明確的終止符。我在上面的腳本中使用了0,但這可能是您的案例中的有效輸入。您可能需要將其更改爲-1或其他特殊值。無論如何,請確保您的數據文件實際上以該值終止。

+0

這很好用,期待a的價值。而不是1我得到0因爲我實際上在做(65536%65536) – egorulz

+0

@egorulz:在什麼輸入? – rici

+0

@egorulz:awk和bc程序都可以在你的示例輸入中正常工作。 – rici

3

有一個解決方案,適合您的需求。但如果它比你的工作更快,我不能說。你可以測試。

這裏我只是在你的例子中用一個數字測試,你可以把它包裝在一個循環中。

kent$ printf "%064s\n" "$(bc <<< "obase=2;4435738625")"|sed -r 's/.{16}/ibase=2;&\n/g'|bc 
1 
2148 
1 
0

使用bcobase集,並且其documented behaviour

對於鹼大於16,BC使用印刷,其中每個基數較高位被打印爲基座10號數的一個多字符碼方法。多字符數字由空格分隔。

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

和管道將進入awk如果你需要巧妙輸出一點,例如丟棄前導零,或處理的列數的變量(如果4列≥2 ,3如果≥2 等):

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

<(echo ...)部件允許bc讀取echo輸出作爲文件,將這些行添加到每個輸入文件的頂部和底部的快速替代方法。

相關問題