相当于Linux的egrep在PHP中的文本文件目录?

bla*_*arg 2 php linux

我想在PHP中搜索文本文件的目录,并列出发生字符串的所有实例.

在Linux中我会用这个:

egrep Cheese textfile_*.txt
Run Code Online (Sandbox Code Playgroud)

PHP中是否有一个函数能够实现这一功能,而不必先将所有内容附加到数组中?

Dav*_*dom 6

一般情况

假设您希望解决方案在任意数量的任意大小的文件中匹配任意长度的字符串,并且您的系统资源是有限的.这很可能是场景,也是最棘手的.

你不能简单地将所有文件加载到内存中并将它们作为每个文件的一个大字符串进行搜索,因为这非常耗费内存,并且在功能复杂性方面实际上并不是特别有效(你循环所有文件,将它们加载到内存中,然后循环它们)再次搜索内容).

事实上,最好避免将整个文件加载到内存中 - 如果其中一个文件是10GB呢?

所以,首先,很明显,我们需要获取目录中的文件列表.有几种方法 - 我看到glob()过几次 - 但我会说这个算法的最佳方法是按顺序读取条目并一次处理一个,而不是将整个列表加载到数组中然后迭代它,在PHP中意味着你要么想要opendir()函数族,要么想要一个DirectoryIterator迭代器类家族.许多人会争辩说,在现代PHP中,后者是"正确的"方式.

现在您可以访问目录中的文件列表,您需要访问内容,而无需将整个文件加载到内存中.在PHP中,这意味着你将要fopen()和(因为这是一个文本文件)fgets().这允许我们一次处理一行文件,因此我们永远不会一次将多行数据加载到内存中.它还有一个允许您指定最大行长度的参数,如果文本文件由于某种原因包含很少/没有换行符,则应该使用它.

所以我们以块的形式处理文件,我们只能strpos()搜索字符串的每个块,对吧?好吧,差不多.当搜索字符串跨越两个(或更多)块的边界时会发生什么?这是它开始变得有趣的地方,以及它开始变得值得研究更复杂的字符串搜索算法(Boyer-Moore算法的一个变体可能在这里很好地服务于你).

现在你唯一需要确定的是你想要匹配的具体程度 - 你想要区分大小写吗?你想原谅空白差异吗?你想标准化字符集吗?在实现字符串搜索算法之前,必须回答和解决这些问题.

这种情况的实际情况是,这些复杂性中的一些在PHP中解决起来相对较慢 - 如果你最终一次迭代字符串一个字符,例如,在C中可以非常快的东西,它将成为PHP中真正的性能杀手.

你的案子

......可能不需要这种复杂性.如果你知道你将永远处理少量相当小的文件,那么简单地采用strpos(file_get_contents())组合方法很可能会很好 - 尽管你做了什么,一次处理一个文件而不是在执行任何文件之前将它们全部加载到内存中可能需要搜索操作.


从本质上说,如何实现这取决于对环境的几个因素,您正在使用-但这样的事情可能是在资源消耗方面很危险的,你必须考虑你的代码是如何需要现在的工作和未来前你可以建立正确的解决方案.

  • @blarg嗯,我可以直接告诉你,你永远无法在PHP中匹配已编译的二进制可执行文件的速度,真的可以用于任何事情.如果速度是你最关心的,那么只需调用egrep.但是如果你保持你的代码优化(这可能相当于复杂和不可维护),你可能会得到一些可用于该数据量的东西. (2认同)