我有 250 个字符串,我需要计算每个字符串在 400 个文件(最多 20,000 行)的每一行中出现的次数。字符串示例:
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
编辑:我像这样粘贴了 400 次,其中 x 是原始文件中的行数。
paste out/file1_{1..x}.txt > out/file1_all.txt
有谁知道如何加快速度?
答案1
如果
$ cat strings
journal
moon pig
owls
和
$ cat file
I like to journal about owls and moon pigs.
owls are birds. moon pigs are not.
owls owls owls
然后,你可以像这样使用 GNU awk
gawk '
NR == FNR { string[++n] = $0; next}
{
for (i=1; i<=n; i++)
# gsub() return the number of replacements.
# it is a convenient way to count instances of fixed strings.
count[i][FNR] = gsub(string[i], string[i])
if (FNR > max)
max = FNR
}
END {
for (i=1; i<=n; i++) {
for (j=1; j<=max; j++)
printf "%s\t", 0 + count[i][j]
print ""
}
}
' strings file
输出
1 0 0
1 1 0
1 1 3
我根本没有解释过那个 awk 程序。看看你是否能弄清楚,并提出你的任何问题。
答案2
获取每行计数数组并立即处理每行的核心算法是:
gawk ' NR == FNR { string[++n] = $0; next}
{ for (i=1; i<=n; i++)
printf("%s\t", gsub(string[i],""))
print ""
}
' strings file
这是基于 gsub 来给出执行的替换的计数。
这将生成以下输出:
1 1 0
0 0 2
这只是您所要求的转置矩阵。在 awk 中转置列和行有点复杂。并且还可以处理多个文件。我们可以使用空行作为文件更改的指示符来连接(管道)两个脚本。处理同一个文件两次:
awk '
NR == FNR { string[++n] = $0; next}
FNR==1 && p == 1 { print "" }
{ for (i=1; i<=n; i++) printf("%s\t", gsub(string[i],""))
print ""
p = 1
}
END { print "" }
' strings.txt infile.txt infile.txt |
awk '!/^$/{
for(i=1;i<=NF;i++) f[NR-r][i]=$i ;
if (maxf<NF) maxf = NF ;
if (maxr<(NR-r)) maxr = NR-r ;
}
/^$/{
for( i=1 ; i<=maxf ; i++ )
{
for( j=1 ; j<=maxr ; j++ )
printf("%s\t",f[j][i])
print ( "loop", maxf, maxr, r )
}
r=NR
print ( "" )
maxf=0
maxr=0
delete f
}'
这给出了所问的答案:
1 0
1 0
0 2
1 0
1 0
0 2