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

时间:2015-01-29 10:50:08

标签: php linux shell

我有两个文件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中的此记录,否则,我们不需要该行,我们也不需要/product/80x80/5252352/因为它的文件夹不是图像。

我在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天。那我该怎样改进呢?可以用其他语言来实现,但我对其他语言并不熟悉,所以请告诉我更多细节。

2 个答案:

答案 0 :(得分:2)

当您拥有一个充满模式的文件和另一个搜索这些模式的文件时,您可以使用-f的{​​{1}}选项(grep仅用作您的模式文件包含固定字符串,而不是正则表达式模式):

-F

要忽略任何以斜杠结尾的内容,您可以再次使用grep -Ff ids.txt urls.log 管道grep来排除模式:

-v

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

答案 1 :(得分:0)

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