각 줄의 중복을 무시하고 .csv 파일에서 가장 일반적인 단어를 찾는 방법은 무엇입니까?

각 줄의 중복을 무시하고 .csv 파일에서 가장 일반적인 단어를 찾는 방법은 무엇입니까?

.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

sortcoreutils를 사용할 수밖에 없다면 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

작동 방식은 다음과 같습니다.

  • 입력 파일의 각 줄에 대해 다음을 수행합니다.
  • i0으로 다시 초기화 하고 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

관련 정보