有效地 grep 排序文件的间隔

kat*_*osh 7 performance shell-script text-processing

我的文件有数百万行,驻留在内存中/dev/shm/tmp.file,被多个线程访问,看起来像这样

831092,25a1bd66f2eec71aa2f0a8bb3d,/path/to/a/file
4324,8d83c29e4d8c71bd66f1bd66fs,/path/to/another/file
...
Run Code Online (Sandbox Code Playgroud)

和由第二后的部分排序,sort -t , -k3。一般来说,每一行都有形状[0-9]*,[0-9a-z]*,.*,文件路径可以包含除\0or之外的任何字符\n

我需要尽快提取驻留在给定目录中的所有文件的行,而不需要制作额外的副本。由于文件是这样排序的,我正在寻找的行是文件的一个不间断的块。

目前我使用,grep -F ',<directory>' /dev/shm/tmp.file但我知道对第一个命中进行二分搜索然后逐行扩展块或使用另一个二分搜索会更快,而不用读取每个新行的整个文件。但是,这必须集成到 bash 脚本中,我发现无法在 bash 中执行类似 lseek 的操作。

sgrep但它需要对完整的行进行排序。

如何以',<directory>'更快的速度提取所有匹配项grep -F

编辑:输入/dev/shm/tmp.file仅用于进行此类提取。因此,以某种方式对其进行预处理以使工作更容易是一种选择。

编辑: a.ba和之间排序a/b不是问题,因为所有子目录都应包含在块中。

Sté*_*las 11

如果您更改831092,25a1bd66f2eec71aa2f0a8bb3d,/path/to/a/file/path/to/a/file,831092,25a1bd66f2eec71aa2f0a8bb3d

你可以这样做:

look /path/to/ /dev/shm/tmp.file
Run Code Online (Sandbox Code Playgroud)

look是 70 年代的传统 Unix 实用程序,未由 POSIX 指定但相当普遍。在 Debian 和衍生产品上,您会在bsdmainutils软件包中找到一个,在 util-linux 中也有一个(也是从 BSD 复制的,而不是在 Debian 软件包中的同名)。

look mmap()s 文件并进行二进制搜索。

但是请注意,grep除非您通过-b选项(叹气),否则Debian 实现将恢复为基本线性搜索。因此,在 Debian 或衍生版本上,您需要:

look -b /path/to/ /dev/shm/tmp.file
Run Code Online (Sandbox Code Playgroud)

另请注意,某些实现对它们可以处理的文件大小有限制(请参阅 Debian 补丁的相应错误