如何从 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.
中的每一行
我有两个文件,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.
中的每一行