如何使用 Linux 排序实用程序按固定字节偏移量对二进制键值对进行排序?

Bre*_*ter 4 sort

我想对一个 20GB 的二进制文件进行排序,该文件包含以连续方式放置的 30 字节键和 20 字节值。一切都在一条线上。我想指定排序必须用于比较的键长度和记录大小。这样,当键移动时,与其关联的值也会移动。

理想情况下,我不想以任何方式修改文件(即在键和值之间添加分隔符)。该文件看起来像KVKVKVKVKVKV. 单行二进制文件。

20GB 文件的前 200B 的 Hexdump:

# hexdump -n 200 -C 20gbUnsorted
00000000  54 65 73 74 69 6E 67 31  32 33 65 08 00 60 83 6b  |Testing123e..`.k|
00000010  39 2c d5 8b 8f 5e 55 96  18 55 e7 9b 87 f0 22 83  |9,...^U..U....".|
00000020  a4 66 b6 aa b1 f9 e0 ca  cf 1e 26 b3 29 2a fd 10  |.f........&.)*..|
00000030  64 bb 18 b5 6a c0 7d 6f  65 6b 1d 2f 43 0d 57 bd  |d...j.}oek./C.W.|
00000040  e7 e4 7d 81 f3 6a 6d d2  67 94 8b bc 23 97 bf e2  |..}..jm.g...#...|
00000050  8c 33 4e 4a d8 2b 8e 70  16 62 93 cf aa 01 16 bf  |.3NJ.+.p.b......|
00000060  da 3b b1 ab 95 e0 e4 82  62 b3 ed fe 04 47 b5 7f  |.;......b....G..|
00000070  77 b1 3a 35 87 fb e7 90  42 e3 c4 06 d6 8e 9f d2  |w.:5....B.......|
00000080  c7 f3 f6 39 0d 9d 0d ce  13 fb 83 42 e1 52 81 2e  |...9.......B.R..|
00000090  99 4b 4b 40 3a 16 7a 2a  7c 93 c3 84 1d e1 93 0a  |.KK@:.z*|.......|
000000a0  0d b2 07 f4 eb 9e 04 b5  9e d8 77 d9 a1 a0 67 a1  |..........w...g.|
000000b0  01 fa 8d 8d 4c 04 5b ee  a3 00 6f b4 20 50 a4 e6  |....L.[...o. P..|
000000c0  5b b3 cc 40 83 eb b2 ad                           |[..@....|
000000c8

Run Code Online (Sandbox Code Playgroud)

我正在使用Linux。

Phi*_*pos 6

这感觉很难看,但它应该有效:

hexdump -v -e '50/1 "%02x " "\n"' file.bin | sort | xxd -p -r > file-sorted.bin
Run Code Online (Sandbox Code Playgroud)

hexdump按每行 50 个字节进行分组,对sort这些行执行普通操作,然后使用xxd -r.

我不关心仅对前 30 个字节进行排序,因为如果它们相同,则顺序是开放的,我选择继续按值排序。


gle*_*man 5

IMO,用编程语言更容易管理,可以轻松读取/写入二进制文件。对于(一个深奥的)例子,Tcl:

\n
tclsh <<\'END_TCL\'\n    set fh [open file.bin rb]\n    while {true} {\n        set kv [read $fh 50]\n        if {[string length $kv] != 50} break\n        lappend kvs $kv\n    }\n    close $fh\n\n    set fh [open file_sorted.bin wb]\n    foreach kv [lsort $kvs] {puts -nonewline $fh $kv}\n    close $fh\nEND_TCL\n
Run Code Online (Sandbox Code Playgroud)\n

这是输入文件:

\n
tclsh <<\'END_TCL\'\n    set fh [open file.bin rb]\n    while {true} {\n        set kv [read $fh 50]\n        if {[string length $kv] != 50} break\n        lappend kvs $kv\n    }\n    close $fh\n\n    set fh [open file_sorted.bin wb]\n    foreach kv [lsort $kvs] {puts -nonewline $fh $kv}\n    close $fh\nEND_TCL\n
Run Code Online (Sandbox Code Playgroud)\n

以及输出文件:

\n
$ ls -l file.bin\n-rw-r--r-- 1 glennj glennj 200 Apr 20 16:07 file.bin\n\n$ od -c -w50 file.bin\n0000000   T   e   s   t   i   n   g   1   2   3   e  \\b  \\0   ` 203   k   9   ,   \xef\xbf\xbd 213 217   ^   U 226 030   U   \xef\xbf\xbd 233 207   \xef\xbf\xbd   " 203   \xef\xbf\xbd   f   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd 036   &   \xef\xbf\xbd   )   *   \xef\xbf\xbd 020   d   \xef\xbf\xbd\n0000062 030   \xef\xbf\xbd   j   \xef\xbf\xbd   }   o   e   k 035   /   C  \\r   W   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   } 201   \xef\xbf\xbd   j   m   \xef\xbf\xbd   g 224 213   \xef\xbf\xbd   # 227   \xef\xbf\xbd   \xef\xbf\xbd 214   3   N   J   \xef\xbf\xbd   + 216   p 026   b 223   \xef\xbf\xbd   \xef\xbf\xbd 001 026   \xef\xbf\xbd   \xef\xbf\xbd   ;   \xef\xbf\xbd   \xef\xbf\xbd\n0000144 225   \xef\xbf\xbd   \xef\xbf\xbd 202   b   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd 004   G   \xef\xbf\xbd 177   w   \xef\xbf\xbd   :   5 207   \xef\xbf\xbd   \xef\xbf\xbd 220   B   \xef\xbf\xbd   \xef\xbf\xbd 006   \xef\xbf\xbd 216 237   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   9  \\r 235  \\r   \xef\xbf\xbd 023   \xef\xbf\xbd 203   B   \xef\xbf\xbd   R 201   . 231   K   K   @   : 026\n0000226   z   *   | 223   \xef\xbf\xbd 204 035   \xef\xbf\xbd 223  \\n  \\r   \xef\xbf\xbd  \\a   \xef\xbf\xbd   \xef\xbf\xbd 236 004   \xef\xbf\xbd 236   \xef\xbf\xbd   w   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   g   \xef\xbf\xbd 001   \xef\xbf\xbd 215 215   L 004   [   \xef\xbf\xbd   \xef\xbf\xbd  \\0   o   \xef\xbf\xbd       P   \xef\xbf\xbd   \xef\xbf\xbd   [   \xef\xbf\xbd   \xef\xbf\xbd   @ 203   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd\n0000310\n
Run Code Online (Sandbox Code Playgroud)\n
\n

出于好奇,我从这样的问题创建了输入文件(bash):

\n
$ ls -l file_sorted.bin\n-rw-r--r-- 1 glennj glennj 200 Apr 20 16:11 file_sorted.bin\n\n$ od -c -w50 file_sorted.bin\n0000000 030   \xef\xbf\xbd   j   \xef\xbf\xbd   }   o   e   k 035   /   C  \\r   W   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   } 201   \xef\xbf\xbd   j   m   \xef\xbf\xbd   g 224 213   \xef\xbf\xbd   # 227   \xef\xbf\xbd   \xef\xbf\xbd 214   3   N   J   \xef\xbf\xbd   + 216   p 026   b 223   \xef\xbf\xbd   \xef\xbf\xbd 001 026   \xef\xbf\xbd   \xef\xbf\xbd   ;   \xef\xbf\xbd   \xef\xbf\xbd\n0000062   T   e   s   t   i   n   g   1   2   3   e  \\b  \\0   ` 203   k   9   ,   \xef\xbf\xbd 213 217   ^   U 226 030   U   \xef\xbf\xbd 233 207   \xef\xbf\xbd   " 203   \xef\xbf\xbd   f   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd 036   &   \xef\xbf\xbd   )   *   \xef\xbf\xbd 020   d   \xef\xbf\xbd\n0000144   z   *   | 223   \xef\xbf\xbd 204 035   \xef\xbf\xbd 223  \\n  \\r   \xef\xbf\xbd  \\a   \xef\xbf\xbd   \xef\xbf\xbd 236 004   \xef\xbf\xbd 236   \xef\xbf\xbd   w   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   g   \xef\xbf\xbd 001   \xef\xbf\xbd 215 215   L 004   [   \xef\xbf\xbd   \xef\xbf\xbd  \\0   o   \xef\xbf\xbd       P   \xef\xbf\xbd   \xef\xbf\xbd   [   \xef\xbf\xbd   \xef\xbf\xbd   @ 203   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd\n0000226 225   \xef\xbf\xbd   \xef\xbf\xbd 202   b   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd 004   G   \xef\xbf\xbd 177   w   \xef\xbf\xbd   :   5 207   \xef\xbf\xbd   \xef\xbf\xbd 220   B   \xef\xbf\xbd   \xef\xbf\xbd 006   \xef\xbf\xbd 216 237   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   \xef\xbf\xbd   9  \\r 235  \\r   \xef\xbf\xbd 023   \xef\xbf\xbd 203   B   \xef\xbf\xbd   R 201   . 231   K   K   @   : 026\n0000310\n
Run Code Online (Sandbox Code Playgroud)\n