2

我一直在网上寻找一种方法来对我拥有的数据类型(LDIF 文件)进行排序,但我还没有找到我想要的东西。已经有一些程序可以完成这种排序,但是它们在处理非常大的数据集时会失败。好吧,对我来说,这些块的价值非常大,大约为 2 GB,即使我有 6 GB 的 RAM 和更多 GB 的交换空间,使用 ldifsort.pl 脚本也会耗尽内存。所以我希望编写一个程序,将数据块存储到硬盘驱动器,对内存中的键进行排序,然后按排序顺序重新组合块。而且我想使用python3,因为我正在尝试学习该语言。因此,如果有人对基本策略或使用 python3 执行此操作的具体方法有建议,我将非常感谢您的帮助。

我有包含 LDAP 数据的大型文本文件,基本上采用(非常简化的)形式:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node1
groups: 1
permissions: 1
IsActive: FALSE
Barring: TRUE

dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node1
groups: 1
permissions: 1
ServiceProfile: Lemur

dn: Subscriber=UniqueName2@domain.com;RestOfTree=node1
groups: 1
permissions: 1
IsActive: FALSE
Barring: TRUE

dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node1
groups: 1
permissions: 1
ServiceProfile: Lemur

每个订阅者还有另外三个与之关联的块(我的示例代码只显示了与订阅者关联的另一个块),我想在排序完成后将所有四个块放在一起。

因此,如果我按此顺序读取 dn(为简洁起见,隐藏了与 dn 关联的数据):

dn: Subscriber=UniqueName2@domain.com;RestOfTree=node
dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node
dn: Subscriber=UniqueName4@domain.com;RestOfTree=node
dn: ProfileID=UniqueName4@domain.com;Subscriber=UniqueName4;RestOfTree=node
dn: Subscriber=UniqueName1@domain.com;RestOfTree=node
dn: Subscriber=UniqueName3@domain.com;RestOfTree=node
dn: ProfileID=UniqueName3@domain.com;Subscriber=UniqueName3;RestOfTree=node
dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node

我希望输出为:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node
dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node
dn: Subscriber=UniqueName2@domain.com;RestOfTree=node
dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node
dn: Subscriber=UniqueName3@domain.com;RestOfTree=node
dn: ProfileID=UniqueName3@domain.com;Subscriber=UniqueName3;RestOfTree=node
dn: Subscriber=UniqueName4@domain.com;RestOfTree=node
dn: ProfileID=UniqueName4@domain.com;Subscriber=UniqueName4;RestOfTree=node

我的一个想法是使用 sqlite3 在 python 读取数据时存储数据,然后在 python 中对键进行排序,然后使用查询再次从 sqlite 提取数据并将数据写入文件。但我担心在 sqlite 中搜索键所花费的时间会过多。然后我想我可以在插入数据的同时对sqlite中的数据进行排序,但是sqlite似乎不支持这个,我不知道是否有另一个数据库系统支持。

任何帮助或方向表示赞赏。

感谢 Zach 提出的仅使用 GNU 排序而不是数据库系统的建议。这是我在他的帮助下开发的解决方案。

awk -f ldifformatter.awk LDAP 数据文件*.ldif | 排序-t \| -k1 | sed '1d;s/|/\n/g' > sorted.txt

其中 ldifformatter.awk 用“|”交换所有换行符 除了用于排序的顶级 dn 之外。

谢谢,生锈

4

3 回答 3

2

您不应该对内存中的数据进行排序。您可以使用合并排序

Guido van Rossum 写了一篇关于相同问题的文章 —使用 Python 在 2MB 的 RAM 中对一百万个 32 位整数进行排序。本文中有代码示例。

于 2013-08-28T15:54:05.363 回答
1

命令行sort实用程序可以对非常大的文本文件进行排序,而无需将它们完全读入内存(至少 GNU 版本可以)。但是,要使用它,您必须重新格式化数据,以便每条记录(应该保存在一起的所有内容)都出现在一行上。如果记录看起来像这样:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node1|groups: 1|permissions: 1|IsActive: FALSE|Barring: TRUE||dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node1|groups: 1|permissions: 1|ServiceProfile: Lemur

然后sort -t \| -k1将完成这项工作。

您可以用 Python 编写一个程序,将数据流式传输到适当格式的临时文件中,调用sortusing subprocess.check_call,然后恢复原始格式。用于tmpfile.NamedTemporaryFile创建临时文件。

于 2013-08-28T15:48:11.380 回答
0

我想知道 SQLite 是否真的不能胜任这项任务。但无论如何,您可以使用外部排序算法,例如 Mergesort,以保持较低的内存使用率。

http://en.wikipedia.org/wiki/External_sorting

于 2013-08-28T15:47:43.130 回答