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
編集:最初の列はファイルの最初の行から始まる文字列を計算し、2番目の列はファイルの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
1行あたりの数の配列を取得し、各行を即座に処理するコアアルゴリズムは次のとおりです。
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で列と行を変更するのは少し複雑です。また、複数のファイルを処理することもできます。ファイル変更マークとして空白行を使用して、2つのスクリプトをリンク(パイプ)できます。同じファイルを2回処理します。
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