如何从 Linux 上的大文件中过滤掉数据?

How to filter out data from big file on Linux?

我有两个文件,urls.log(1Gb) 和 ids.txt(20M),第一个文件 urls.log 看起来像这样:

/product/80x80/436284940/
/product/100x100/1051907917/Pavillon-2.jpg
/product/140x140/988563549/LITTLE-ROSE-Mikrofasermischung-Maxi-Slips-uni-5er-Pack.jpg
/product/100x100/504170379/Dunlop-SP-Sport-Maxx-215-40R17-87V-XL-VW1-MFS.jpg
...

第二个文件 ids.txt 如下所示:

988563549
988563540
988563541
...

结果应该是:(result.txt)

/product/140x140/988563549/LITTLE-ROSE-Mikrofasermischung-Maxi-Slips-uni-5er-Pack.jpg

因为988563549存在于ids.txt中所以我们需要urls.log中的这条记录,否则,我们不需要该行,我们也不需要[=23] =] 因为它是文件夹而不是图像。

我在PHP中写的是:

$file = '/combined/combine.url.sanitized.access_log';
$handle = fopen($file, "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) 
    {
        $handleids = fopen('/script/ids.txt', "r");
        while (($lineIds = fgets($handleids)) !== false) 
        {
            if (strpos($line, trim($lineIds)) !== false) 
            {
                file_put_contents('result.txt', $line . PHP_EOL, FILE_APPEND | LOCK_EX);
                break;
            }
        }
        fclose($handleids);
        file_put_contents('result.txt', '=' . PHP_EOL, FILE_APPEND | LOCK_EX);
    }

    fclose($handle);
}

这个工作好慢,我算了一下时间,大概需要60天。那我应该怎么改进呢?可以用其他语言来实现,但我对其他语言不熟悉,所以请告诉我更多细节。

当你有一个充满模式的文件,而另一个文件要搜索这些模式时,你可以使用 grep-f 选项(-F 用作你的模式文件只包含固定字符串,不包含正则表达式模式):

grep -Ff ids.txt urls.log

要忽略任何以斜杠结尾的内容,您可以再次通过管道传输到 grep,这次使用 -v 排除模式:

grep -Ff ids.txt urls.log | grep -v /$ > result.txt

这应该比您的 PHP 脚本更快。如果仍然太慢,您可能需要考虑使用 Perl(例如 this question)或 Python.

首先,您可以将 ids.txt 缓存到一个集合中。 然后,启动一个反应器线程将每一行迭代 urls.log 到一个队列中, 并启动一些工作线程来使用这个队列,在每个工作线程中,你使用 ids.txt 制作的集合来过滤 urls.log.

中的每一行