高效搜索排序文件


12

我有一个大文件,每行包含一个字符串。我希望能够快速确定文件中是否包含字符串。理想情况下,这将使用二进制印章类型算法来完成。

一些谷歌搜索者显示了look带有-b标志的命令,该标志承诺使用二进制搜索算法查找并输出以给定前缀开头的所有字符串。不幸的是,它似乎无法正常工作,并且为我知道文件中的字符串返回空结果(它们由等效的grep搜索正确返回)。

有谁知道其他实用程序或策略来有效搜索此文件?


最佳答案指出了错误的排序:事实是您必须使用以下look命令进行排序:LC_COLLATE = C sort -d才能使命令正确运行,因为外观似乎忽略了语言环境,并且仅使用C进行了硬编码排序,因此我也打开了一个错误由于存在这种令人困惑的行为:bugzilla.kernel.org/show_bug.cgi?
id=198011

look -b我因错误而失败File too large。我认为它正在尝试将整个内容读入内存。
布莱恩·明顿

Answers:


9

grep和之间有本质区别look

除非另有明确说明,否则grep即使在行内的某处也会找到模式。对于手册look页状态:

look —显示以给定字符串开头的

我不是look经常使用,但在我刚刚尝试过的一个简单示例中,它的效果很好。


1
我需要搜索的文件大约有110,000,000行。如果我这样做,egrep "^TEST" sortedlist.txt | wc -l 我会得到41,289个结果。但是,等效look命令look -b TEST sortedlist.txt | wc -l仅产生1995年的结果。我几乎想知道是否存在bug look
马特

1
@Matt可能look使用的排序规则设置与用于排序文件的程序不同。
卡巴斯德(Kasperd),2015年

4

也许有点晚答案:

Sgrep将为您提供帮助。

Sgrep(排序的grep)在排序的输入文件中搜索与搜索键匹配的行,并输出匹配的行。搜索大文件时,sgrep比传统的Unix grep快得多,但有很大的限制。

  • 所有输入文件必须按常规文件排序。
  • 排序键必须从行首开始。
  • 搜索键仅在行首匹配。
  • 不支持正则表达式。

您可以在此处下载源代码:https : //sourceforge.net/projects/sgrep/? source =typ_redirect

以及此处的文档:http : //sgrep.sourceforge.net/

其它的办法:

我不知道文件有多大,也许您应该尝试并行操作:

/programming/9066609/fastest-possible-grep

我总是用大于100GB的文件来做grep,效果很好。


2
难道不是已经在askubuntu.com/a/701237/158442吗?
大师

是的,我填写下载链接...
memorybox '18

仅此而已,您应该编辑该帖子,而不是发布新答案。
muru

该帖子推荐:sudo apt-get install sgrep 要获取sgrep,buntu存储库中的sgrep实际上不是此sgrep,但我不确定这是同一件事。
memorybox '18

0

您可以将文件散列为碎片,然后仅对所需的碎片进行grep:

for line in $(cat /usr/share/dict/american-english | tr '[:upper:]' '[:lower:]' | sort | uniq)
do
    prefix=$(echo $line | md5sum - | cut -c 1-2)
    mkdir -p $prefix
    echo $line | gzip >> $prefix/subwords
done

那么查找将如下所示:

    prefix=$(echo $word | md5sum - | cut -c 1-2)
    zgrep -m 1 -w word $prefix/subwords

这有两件事:

  1. 读取和写入压缩文件。通常,将负载放在CPU(非常快)而不是磁盘(非常慢)上会更快
  2. 为了使哈希值大致相等,可以根据需要使用更短或更长的哈希值,以减小每块的大小(但如果这样做,我建议使用嵌套的子目录)

0

sgrep可能为您工作:

sudo apt-get install sgrep
sgrep -l '"needle"' haystack.txt

项目页面http://sgrep.sourceforge.net/说:

Sgrep使用二进制搜索算法,该算法非常快,但需要排序的输入。

但是,对于插入,我认为没有比使用数据库更好的解决方案了:https : //stackoverflow.com/questions/10658380/shell-one-liner-to-add-a-line-to-a-sorted-file/ 33859372#33859372


3
sgrep在Ubuntu软件仓库实际上是这个sgrep,其目的是“查找文件的结构化模式”,并已无关的二进制搜索。
ingomueller.net

0

如果您真的想要快速(O(1)快速),则可以构建一个要研究的哈希集。我找不到能够让我将预构建的哈希集存储在文件中并对其进行探测无需将整个文件读入内存的实现,因此我自己开发了一个

构建哈希集(-b/ --build):

./hashset.py --build string-list.txt strings.pyhashset

探查哈希集(-p/ --probe):

./hashset.py --probe strings.pyhashset \
    'Is this string in my string list?' 'What about this one?'

…或使用字符串在标准输入上查找:

printf '%s\n' 'Is this string in my string list?' 'What about this one?' |
./hashset.py --probe strings.pyhashset

如果只对退出状态感兴趣,可以--probe使用-q/ --quiet选项使输出静默:

if ./hashset.py --quiet --probe strings.pyhashset ...; then
    echo 'Found'
else
    echo 'Not found'
fi

有关更多选项,请参见可通过-h/ --help选项或随附README文件访问的用法说明。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.