如何简化基于reference.txt批量统计年份目录文件关键词的操作?
我在home目录下有500多个年份子目录(比如home/2001/、home/2002/等),每个目录下有对应年份的文本文件,示例如下:
home/2001/2001ab.txt内容:the AAAS kill every one not but me and you and etc
the A1CF maybe color of full fill zombiehome/2002/2002ab.txt内容:we maybe know some how what
home/2003/2003ab.txt内容:Mr, Miss boston, whatever
aaas will will will long long
同时home目录下有reference.txt,内容是要统计的关键词列表:
A1BG
A1CF
A2M
AAAS
我的需求是统计每个关键词在各年份目录的文本文件中的出现次数。
目前我会手动切换到每个年份目录,运行以下脚本:
# awk function search () { awk -v pattern="$1" '$0 ~ pattern {print}' *.txt > $1 } # load custom.txt for i in $(cat reference.txt) do search $i done # word count wc -l * > line-count.txt
但这个方法有两个明显问题:
- 要手动切换500个目录执行,操作太繁琐;
- 生成大量临时文件,既耗时又占资源。
一开始想过用grep,但不知道怎么基于reference.txt的关键词列表批量操作,才改用了awk。请问怎么简化这个操作?
方案一:用grep+awk批量完成(推荐)
直接在home目录下执行一条命令就能搞定,不需要进入子目录,也不会生成临时文件:
grep -r -f reference.txt --include="*.txt" home/ | awk -F'/' '{year=$2; sub(/:.*/, "", $NF); key=$NF} {count[year,key]++} END {for (pair in count) {split(pair, arr, SUBSEP); printf("%s\t%s\t%d\n", arr[1], arr[2], count[pair])}}' > result.txt
命令解释:
grep -r -f reference.txt --include="*.txt" home/:递归遍历home下所有.txt文件,用reference.txt里的关键词做匹配,输出格式为文件路径:匹配到的行内容awk部分:- 按
/分割路径,取第二个字段作为年份(比如2001) - 把最后一个字段(即
:行内容)里的:及后面内容去掉,得到匹配到的关键词 - 用二维数组
count[year,key]统计每个年份每个关键词的出现次数 - 最后遍历数组,输出
年份 关键词 次数的格式化结果,保存到result.txt
- 按
如果要忽略关键词的大小写(比如把示例里的AAAS和aaas算作同一个),给grep加-i参数即可,改成grep -r -i -f reference.txt ...。
方案二:优化awk脚本,批量遍历目录
如果你更习惯用awk,也可以写一个脚本批量处理所有年份目录,同样不生成临时文件:
#!/bin/bash awk -v ref="reference.txt" ' BEGIN { # 读取关键词列表到数组 while ((getline line < ref) > 0) { keys[line] = 0 } close(ref) } # 处理每个文件时,先提取年份 FNR == 1 { split(FILENAME, path, "/") year = path[2] } { # 遍历所有关键词,检查当前行是否包含 for (key in keys) { if ($0 ~ key) { count[year, key]++ } } } END { # 输出统计结果 printf("年份\t关键词\t出现次数\n") for (pair in count) { split(pair, arr, SUBSEP) printf("%s\t%s\t%d\n", arr[1], arr[2], count[pair]) } } ' home/*/*.txt > result.txt
使用说明:
- 把上面的内容保存为
count_keywords.sh - 赋予执行权限:
chmod +x count_keywords.sh - 在
home目录下执行:./count_keywords.sh
这个脚本会直接遍历所有年份目录下的.txt文件,统计每个关键词在对应年份的出现次数,结果直接输出到result.txt,全程无临时文件。
内容的提问来源于stack exchange,提问作者Namie Amuro

