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