如何在104GB文件中仅一行搜索特定文本?

问题描述 投票:0回答:3

我刚刚使用 y-cruncher 计算完 1110 亿位 PI 数字,并有 104GB 文件。

我遇到了问题。

我想玩一玩,尝试在那里搜索名称、值、标题等,这是一定的数字序列。 然而,像 grep fgrep 和其他搜索一样,即使内存不足,也会崩溃。

整个数字位于 txt 文件中的一行中。

那么,我现在如何找到那里的文本,无论需要多长时间,最好不要将其分割成小文件或类似的文件,以便文件保持不变。

以及将来如何快速搜索那里,例如创建一个搜索站点并已经在那里使用sql/分区到文件中,或者其他东西,在这里建议一些可以帮助的东西。

提前感谢,我尝试了我所说的 grep、fgrepX 和其他一些开源东西。

linux search grep
3个回答
1
投票

grep
在搜索其中的文本之前将整个文件读入内存。您可以改为使用 GNU awk 进行多字符 RS 并告诉它一次达到
1000
或任何您喜欢的字符数:

gawk -v RS='.{0,1000}' '/regexp/' file

但是您需要考虑匹配的字符串可能会跨越 1000 个字符的边界,因此请确保每个记录足够大以容纳匹配的字符串,并且您测试连接的 2 个记录,例如:

gawk -v RS='.{0,1000}' (prev $0) ~ /regexp/; {prev=$0}' file

上面的内容显然未经测试,因为问题中没有样本输入/输出供我们测试,并且OP没有告诉我们如果/当正则表达式匹配时他们想要输出什么,等等,所以这一切都留给他们了也想弄清楚。


0
投票

如果标准程序不够好,请制作自己的程序。

我用 Rust 为你写了这个。我选择 Rust 是因为它有一个令人印象深刻的 memchr::memmem 库。它应该相当快。它绝对不会耗尽内存。我希望它没有任何错误。在线搜索如何安装 Rust。使用

cargo build --release
编译程序。

fastgrep/src/main.rs:

use std::io::Read;
use std::os::unix::ffi::OsStrExt;

fn main() -> std::io::Result<()> {
    const BUF_SIZE: usize = 8192;

    let args: Vec<_> = std::env::args_os().collect();
    let needle: &[u8] = args[1].as_bytes();
    let filename = &args[2];

    let finder = memchr::memmem::Finder::new(needle);
    let mut file = std::fs::File::open(filename)?;
    let mut offset = 0;
    let mut buffer: Vec<u8> = vec!();

    loop {
        let old_len = buffer.len();
        buffer.resize(old_len + BUF_SIZE, 0);
        let bytes_read = file.read(&mut buffer[old_len..])?;
        buffer.truncate(old_len + bytes_read);
        // eprintln!("old_len {old_len} bytes_read {bytes_read}");

        for offset_in_buffer in finder.find_iter(&buffer) {
            println!("{}", offset + offset_in_buffer);
        }

        if bytes_read == 0 {
            break;
        }

        let advance = buffer.len().saturating_sub(needle.len() - 1);
        // eprintln!("advance {advance}");
        offset += advance;
        buffer = buffer[advance..].to_vec();
    }

    Ok(())
}

fastgrep/Cargo.toml:

[package]
name = "fastgrep"
version = "0.1.0"
edition = "2021"

[dependencies]
memchr = "2.6.4"

Rust 游乐场示例(硬编码参数):
https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=e2385dbb56bdaee15ba4b827245a19e9

祝你好运!请写评论告诉我它是否有效!


0
投票

如果标准程序不够好,请尝试用于搜索二进制文件的程序。

您的文件并不是真正的二进制文件,其中一些程序可能希望您以十六进制写入针,但至少它们不会尝试逐行读取输入。

这篇文章https://www.baeldung.com/linux/binary-files-pattern-search提到了这些工具:

某些 Linux 发行版提供了其中一些工具的软件包。

© www.soinside.com 2019 - 2024. All rights reserved.