.csv 파일에서 가장 일반적인 단어 10개를 찾아야 합니다. 파일은 각 줄에 쉼표로 구분된 단어가 포함되도록 구성되어 있습니다. 같은 줄에 같은 단어가 여러 번 반복되면 1로 계산됩니다. 따라서 아래 예에서는 다음과 같습니다.
green,blue,blue,yellow,red,yellow
red,blue,green,green,green,brown
녹색, 파란색, 빨간색은 2로 계산하고, 노란색과 갈색은 1로 계산합니다.
비슷한 질문이 이전에 요청된 것으로 알고 있으며 한 가지 해결책은 다음과 같습니다.
<file.csv tr -c '[:alnum:]' '[\n*]' | sort|uniq -c|sort -nr|head -10
그러나 이는 다음과 같이 단어가 같은 줄에 나타나는 횟수를 계산합니다.
4 green
3 blue
2 yellow
2 red
1 brown
이것은 실제로 나에게 필요한 것이 아닙니다. 도움이 필요하세요? 또한 명령에 대한 간략한 설명과 비슷한 질문에서 찾은 명령이 필요한 작업을 수행하지 않는 이유에 대해 감사하겠습니다.
답변1
GNU grep
또는 호환 제품을 사용하세요.
$ grep -nEo '\w+' file.csv|sort -u|cut -d: -f2-|sort|uniq -c|sort -k1rn|head
2 blue
2 green
2 red
1 brown
1 yellow
답변2
나는 펄을 선택할지도 모른다
uniq
모듈 의 콘텐츠를 사용하여List::Util
각 행의 중복 항목을 제거합니다.- 해시를 사용하여 결과 발생 횟수를 계산합니다.
예를 들어
perl -MList::Util=uniq -F, -lnE '
map { $h{$_}++ } uniq @F
}{
foreach $k (sort { $h{$b} <=> $h{$a} } keys %h) {say "$h{$k}: $k"}
' file.csv
2: red
2: green
2: blue
1: yellow
1: brown
sort
coreutils를 사용할 수밖에 없다면 uniq
쉘 루프를 추가하여 유사한 알고리즘을 구현할 수 있습니다.
while IFS=, read -a words; do
printf '%s\n' "${words[@]}" | sort -u
done < file.csv | sort | uniq -c | sort -rn
2 red
2 green
2 blue
1 yellow
1 brown
하지만 참고해주세요쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?
답변3
awk
연관 배열과 간단한 논리 검사를 사용할 수 있습니다 .
awk -F, '
{split("", c); for (i=1; i<=NF; i++)
if (!c[$i]){c[$i]++;wds[$i]++}}
END{for (wd in wds) print wds[wd], wd}' file
산출
1 brown
2 red
1 yellow
2 blue
2 green
송곳
필드 구분 기호를 다음으로 설정하세요.,
awk -F, '
한 줄에 여러 단어가 나타나는지 확인하기 위해 계산 c
하므로 또는 를 사용하여 각 줄 시작 부분의 단어 개수가 비어 있는지 확인한 delete c;
다음 split("", c)
필드를 반복합니다.
{split("", c); for (i=1; i<=NF; i++)
또는
{delete c; for (i=1; i<=NF; i++)
$i
이 줄에 있는 단어를 아직 보지 못했다면 !c[$i]
해당 단어에 대한 카운터를 c[$i]++
1로 늘립니다(단어가 같은 줄에 다시 나타나면 조건부 테스트가 실패합니다). 그런 다음 wds[$i]++
테스트가 실패하지 않으면 전체 개수를 늘립니다. 단어의
if (!c[$i]){c[$i]++;wds[$i]++}}
파일이 완성되면 배열을 반복하고 wds
개수 wds[wd]
와 단어를 인쇄하십시오.wd
END{for (wd in wds) print wds[wd], wd}' file
재미로
awk
연관 배열 비트가 없는 해킹
awk -F, '{for (i=1; i<=NF; i++) print NR, $i}' file |
sort | uniq | awk '{print $2}'| sort | uniq -c | sort -nr
awk
줄 번호가 앞에 오도록 필드를 삭제한 다음 sort | uniq
줄 중복을 잃고 awk
번호를 다시 잃은 다음 원래 코드로 되돌립니다.
답변4
awk에는 주요 필수 작업을 수행하는 스크립트가 있습니다.
awk -F, '
{
i = split( "" , seen ) ;
while( ++i <= NF ) if( ++seen[$i] == 1 ) count[$i]++;
}END{
for( word in count ) print count[word] , word
}' file | sort -rn | head
작동 방식은 다음과 같습니다.
- 입력 파일의 각 줄에 대해 다음을 수행합니다.
i
0으로 다시 초기화 하고seen
새 행마다 배열을 지웁니다i=split("",seen)
.seen
각 필드에 대한 배열 생성++seen[$i]
- 이 행에서 a 필드가 처음 표시될 때 해당 필드의 수를 계산합니다. (
count[$i]++
). - 모든 라인이 처리되면
END
, for( word in count )
계산 된 각 단어에 대해- 모든 단어와 그 수를 인쇄합니다
print count[word] , word
. - 마지막으로 awk가 출력을 생성한 후 숫자로 정렬합니다.
sort -rn
- 처음 10개 행을 선택합니다
head
.
우리는 이것을 좀 더 신비한 한 줄로 작성할 수 있습니다:
awk -F, '{i=split("",a);while(++i<=NF)a[$i]++||c[$i]++}END{for(i in c)print c[i],i}' file|sort -rn|head