You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Bash Shell脚本在大文件中执行多轮文本搜索需求

高效处理大型电子书列表文件的多次Bash搜索方案

嘿,我来给你捋捋怎么高效处理这个大型电子书列表的多次搜索问题——毕竟大文件反复读太费时间了,得找些省劲儿的办法!

临时多次搜索:用grep提速

如果你只是临时要做几次搜索,不想折腾预处理,那给grep加个--mmap参数就能提速不少。这个参数会用内存映射代替常规的文件读取,大文件下速度提升很明显。

因为原文件的条目是多行结构,所以需要用-A(显示匹配行后N行)和-B(显示匹配行前N行)来获取完整的条目信息,比如:

# 搜索ETEXT NO.56900的完整条目(可根据实际结构调整-A/-B的数字)
grep --mmap -A 2 -B 0 "56900" your_large_file.txt

# 搜索所有芬兰语的书籍
grep --mmap -B 3 -A 0 "\[Language: Finnish\]" your_large_file.txt

# 搜索作者Robert Lloyd Praeger的作品
grep --mmap -B 1 -A 1 "by Robert Lloyd Praeger" your_large_file.txt

频繁搜索:先预处理成结构化文件

要是你需要反复查询这个文件,那最好先把它转成结构化的格式(比如CSV),这样后续搜索会更精准、更高效。原文件格式有点零散,我们可以用awk写个小脚本把每个条目整合成一行:

awk '
BEGIN {
    print "title,author,etext_no,subtitle,language"
}
/by / {
    author = substr($0, 4);
    gsub(/^[[:space:]]+|[[:space:]]+$/, "", author);
    if (current_title != "") {
        printf "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", current_title, author, etext_no, subtitle, language;
        current_title = ""; subtitle = ""; language = ""; etext_no = "";
    }
    next;
}
/\[Subtitle: / {
    subtitle = substr($0, 12);
    gsub(/\]$/, "", subtitle);
    next;
}
/\[Language: / {
    language = substr($0, 12);
    gsub(/\]$/, "", language);
    next;
}
/[0-9]+$/ {
    split($0, parts, /, [0-9]+$/);
    current_title = parts[1];
    gsub(/^[[:space:]]+|[[:space:]]+$/, "", current_title);
    etext_no = substr($0, length(parts[1])+2);
    next;
}
END {
    # 处理最后一个未写入的条目
    if (current_title != "") {
        printf "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", current_title, author, etext_no, subtitle, language;
    }
}
' your_large_file.txt > books.csv

生成books.csv之后,搜索就简单多了,比如:

# 搜索作者Robert Lloyd Praeger的作品
awk -F ',' '$2 == "\"Robert Lloyd Praeger\""' books.csv

# 搜索所有芬兰语书籍
awk -F ',' '$5 == "\"Finnish\""' books.csv

# 搜索ETEXT编号56898的条目
awk -F ',' '$3 == "\"56898\""' books.csv

复杂多条件搜索:用awk一次性处理

如果有多个搜索需求,不想多次读取大文件,那可以直接写个awk脚本,一次性完成所有查询,只需要读一次文件,效率拉满:

awk '
# 先定义你要搜索的目标条件
BEGIN {
    target_etext = "56900";
    target_author = "Robert Lloyd Praeger";
    target_lang = "Finnish";
    print "=== 搜索结果 ===";
}
/by / {
    current_author = substr($0, 4);
    gsub(/^[[:space:]]+|[[:space:]]+$/, "", current_author);
    next;
}
/\[Subtitle: / {
    current_subtitle = substr($0, 12);
    gsub(/\]$/, "", current_subtitle);
    next;
}
/\[Language: / {
    current_lang = substr($0, 12);
    gsub(/\]$/, "", current_lang);
    next;
}
/[0-9]+$/ {
    split($0, parts, /, [0-9]+$/);
    current_title = parts[1];
    gsub(/^[[:space:]]+|[[:space:]]+$/, "", current_title);
    current_etext = substr($0, length(parts[1])+2);
    
    # 检查每个条件并输出结果
    if (current_etext == target_etext) {
        print "\n--- ETEXT No." target_etext " ---";
        print "标题: " current_title;
        print "作者: " current_author;
        print "副标题: " (current_subtitle ? current_subtitle : "无");
        print "语言: " (current_lang ? current_lang : "无");
    }
    if (current_author == target_author) {
        print "\n--- 作者 " target_author " ---";
        print "标题: " current_title;
        print "ETEXT编号: " current_etext;
        print "副标题: " (current_subtitle ? current_subtitle : "无");
        print "语言: " (current_lang ? current_lang : "无");
    }
    if (current_lang == target_lang) {
        print "\n--- 语言 " target_lang " ---";
        print "标题: " current_title;
        print "作者: " current_author;
        print "ETEXT编号: " current_etext;
        print "副标题: " (current_subtitle ? current_subtitle : "无");
    }
    
    # 重置当前条目变量
    current_author = ""; current_subtitle = ""; current_lang = "";
}
' your_large_file.txt

这个脚本可以根据你的需求修改BEGIN块里的目标条件,一次性输出所有匹配的结果,非常适合批量查询。

内容的提问来源于stack exchange,提问作者Azazel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:29:39