我有250个字符串,我需要计算每个字符串出现在400个文件(最多20000行)的每一行上的次数。字符串示例:

journal
moon pig
owls

我的文件示例:

This text has journal and moon pig
This text has owls and owls

示例输出:

1   0
1   0
0   2

我有工作代码,但显然很慢。我相信awk可以加快速度,但我写得不够好。

for file in folder/*
do
    name=$(basename "$file" .txt)
    linenum=1
    while read line
    do
        while read searches
        do
            ###count every time string appears on line and save
            count=$(echo $line | grep -oi "$searches" | wc -l)
            echo $count >> out/${name}_${linenum}.txt
        done < strings.txt
        linenum=$((linenum+1))
    done < $file
done

paste out/example_{1..500}.txt > out/example_all.txt

有人知道怎么加快速度吗?

最佳回复

脚本中的瓶颈可能是循环 while read line 就像你说的一些文件可以有两万行。对于单个搜索模式 grep 已经可以计算一个文件中的所有匹配项,并且比循环快得多 bash . grep 也可以同时处理多个文件,因此外部循环 for file in folder/* 可以替换为一个调用 grep 我也是。

grep -c pattern file1 file2 file3 …

…将按如下方式打印每个文件的匹配项(同一行中的多个匹配项仅计数一次)

file1:7
file2:0
file3:1
…

在下面,我们提取匹配计数(使用 grep 再次)并将列转置为一行(使用 tr ). 然后我们对每个 patternstrings.txt .

while read -r pattern; do
    grep -ci "$pattern" folder/* | grep -Eo '[0-9]+$' | tr \n \t
    echo
done < strings.txt

在这里我用 grep -i 就像你的剧本一样。您也可以使用 -F , -w , ... 取决于你想如何匹配你的模式。

这个脚本仍然有点低效,因为 folder/ 将被读取250次(=行数 strings.txt )一次又一次。但是,在正常情况下,它应该比以前快。试试看,如果你需要更复杂的东西就回来。