我的文件夹中有 5000 个文件。这些文件被命名为 XX0000001 到 XX0005000
我正在尝试从每个文件中获取单词,然后 grep 它们以及另一个文件中的下一行(target.txt)
我的一些 XX* 文件中有大约 30,000 个单词
有什么办法可以做到这一点吗?
我努力了 :
start_number=0000001
end_number=0005000
words_file=target.txt
output_folder="output_results"
mkdir -p "$output_folder"
for ((i=start_number; i <=end_number; i++)); do
filename="XX$(printf "%07d" "$i")"
output_file="$output_folder/output_${filename}.txt"
while read -r word; do
awk -v word="$word" '{for (i=1; i<=NF; i++) if($1 ~ word) {print; next}}' "$filename" >> "$output_file"
done < "$words_file"
done
有没有更快的方法来做到这一点?我的目标文件有数百万行需要搜索;精确目标文件大小为 20 GB,106441678 行
例如:XX0000001 文件看起来像:
Big1 Big5 Big7 Big10 Big11(还有更多的单词;某些 XX 文件甚至可能有多达 30k 单词)
Target.txt 文件如下所示:
#大1
这_是_文件_包含_xxxxx
#大2
这_是_文件_包含_xxxxx
#Big3
这_是_文件_包含_xxxxx
#Big4
这_是_文件_包含_xxxxx
#Big5
这_是_文件_包含_xxxxx
#Big6
这_是_文件_包含_xxxxx
#Big7
这_是_文件_包含_xxxxx
#Big8
这_是_文件_包含_xxxxx
#Big9
这_是_文件_包含_xxxxx
#Big10
这_是_文件_包含_xxxxx
#Big11
这_是_文件_包含_xxxxx
#Big12
这_是_文件_包含_xxxxx
您正在一个非常大的文件中搜索大量搜索词,您不太可能在 shell/标准工具中找到“快速”解决方案。也就是说,我认为你的方法效率特别低。
也许是这样的(未经测试):
但坦率地说,我也不认为这会很快。
这可能是多线程的,这可能会提高吞吐量。
这是一个多线程替代方案。您需要将该值调整
threads
为适合您的操作环境的值。从中获得的任何好处都将取决于硬件因素,例如可用内存、CPU 核心数量、存储速度以及服务器上的其他活动。
要循环一组文件,请使用 shell glob,例如
for f in XX0*
此处。如果您确实需要循环一组数字,则需要注意前导零,就像在 Bash 中一样,它们将数字标记为八进制。例如尝试你的循环,但只是打印数字并查看最后一个:我们看到输出是
2560
,不是5000
。不过,zsh 中的情况并非如此,并且您没有提及您正在运行哪个 shell,但是这个问题可能值得指出。这里,
我不太确定这是做什么的,但我只是注意到,在 AWK 脚本中,您循环遍历输入行的所有字段,但随后您只引用
$1
循环内的字段 1 ( )。现在,我假设您的文件如下所示:
即文件中的一行中有多个不同的模式(例如
Big1
和) (而不是例如每行一个)。另外,我想您想找到与任何模式匹配的行,然后将它们与下一行一起打印。Big7
XX0*
target.txt
现在,标准 grep 可以在匹配后打印“多一行”,并且可以同时查找多个模式。该
-f
选项采用文件的名称,该文件的行形成模式,因此您必须预处理XX0*
文件以使每个模式显示为单行。您可以通过将所有空格更改为换行符来做到这一点tr
。tr
最简单的方法是使用进程替换将to的输出grep
作为文件使用,但您也可以使用临时文件(或者甚至可以将输出通过管道传输到tr
togrep -f -
)例如:
当然,该模式
Big1
也出现在该行上#Big10
,因此它是匹配的。(但是您可以尝试-w
使用 grep 选项来请求全字匹配。)如果您想删除分隔--
符,您可以通过管道传输结果grep -ve --
。其效率如何可能取决于您的 grep 实现,但作为一个为此目的而设计的工具,它可能比在 shell 脚本中执行相同的操作有更好的机会进行优化。Shell 脚本速度很慢。如果所有模式均为 格式
Big*
,明智的做法是仅查找公共部分一次。也许可以将模式列表更改为单个模式,Big(1|5|7|10)
希望它能更好地为正则表达式引擎工作。