[bash] Bash의 열에서 고유 값 수 가져 오기

여러 열이있는 탭으로 구분 된 파일이 있습니다. 폴더의 모든 파일에 대해 열에서 다른 값의 발생 빈도를 계산하고 내림차순으로 정렬합니다 (가장 높은 개수부터). Linux 명령 줄 환경에서이 작업을 어떻게 수행합니까?

awk, perl, python 등과 같은 일반적인 명령 줄 언어를 사용할 수 있습니다.



답변

2 열의 빈도 수를 보려면 (예 🙂

awk -F '\t' '{print $2}' * | sort | uniq -c | sort -nr

fileA.txt

z    z    a
a    b    c
w    d    e

fileB.txt

t    r    e
z    d    a
a    g    c

fileC.txt

z    r    a
v    d    c
a    m    c

결과:

  3 d
  2 r
  1 z
  1 m
  1 g
  1 b


답변

다음은 셸에서 수행하는 방법입니다.

FIELD=2
cut -f $FIELD * | sort| uniq -c |sort -nr

이것은 bash가 잘하는 일입니다.


답변

GNU 사이트는 단어와 자신의 주파수를 모두 출력이 좋은 awk 스크립트를 제안합니다.

가능한 변경 :

  • 당신은을 통해 파이프를 수 sort -nr(및 역방향 wordfreq[word]) 순으로 결과를 볼 수 있습니다.
  • 특정 열을 원하면 for 루프를 생략하고 간단히 작성할 freq[3]++수 있습니다. 3을 열 번호로 바꿉니다.

여기에 간다 :

 # wordfreq.awk --- print list of word frequencies

 {
     $0 = tolower($0)    # remove case distinctions
     # remove punctuation
     gsub(/[^[:alnum:]_[:blank:]]/, "", $0)
     for (i = 1; i <= NF; i++)
         freq[$i]++
 }

 END {
     for (word in freq)
         printf "%s\t%d\n", word, freq[word]
 }


답변

Perl

이 코드는 모든 열의 발생을 계산하고 각 열에 대해 정렬 된 보고서를 인쇄합니다.

# columnvalues.pl
while (<>) {
    @Fields = split /\s+/;
    for $i ( 0 .. $#Fields ) {
        $result[$i]{$Fields[$i]}++
    };
}
for $j ( 0 .. $#result ) {
    print "column $j:\n";
    @values = keys %{$result[$j]};
    @sorted = sort { $result[$j]{$b} <=> $result[$j]{$a}  ||  $a cmp $b } @values;
    for $k ( @sorted ) {
        print " $k $result[$j]{$k}\n"
    }
}

텍스트를 columnvalues.pl로 저장합니다. 다음으로
실행합니다. perl columnvalues.pl files*

설명

최상위 while 루프에서 :
* 결합 된 입력 파일의 각 행에 대해 루프
* 행을 @Fields 배열로 분할
* 모든 열에 대해 결과 배열 해시 데이터 구조 증가

최상위 for 루프에서 :
* 결과 배열에 대한 루프 *
열 번호 인쇄
* 해당 열에 사용 된
값 가져 오기
* 발생 횟수를 기준으로 값 정렬 * 값에 따라 보조 정렬 (예 : b vs g vs m vs z)
* 정렬 된 목록을 사용하여 결과 해시를 반복합니다.
* 각 항목의 값과 수를 인쇄합니다.

@Dennis에서 제공 한 샘플 입력 파일을 기반으로 한 결과

column 0:
 a 3
 z 3
 t 1
 v 1
 w 1
column 1:
 d 3
 r 2
 b 1
 g 1
 m 1
 z 1
column 2:
 c 4
 a 3
 e 2

.csv 입력

입력 파일이 .csv 인 경우 다음 /\s+/으로 변경하십시오 ./,/

난처

추악한 대회에서 Perl은 특히 잘 갖추고 있습니다.
이 한 줄짜리는 다음과 같은 역할을합니다.

perl -lane 'for $i (0..$#F){$g[$i]{$F[$i]}++};END{for $j (0..$#g){print "$j:";for $k (sort{$g[$j]{$b}<=>$g[$j]{$a}||$a cmp $b} keys %{$g[$j]}){print " $k $g[$j]{$k}"}}}' files*


답변

루비 (1.9+)

#!/usr/bin/env ruby
Dir["*"].each do |file|
    h=Hash.new(0)
    open(file).each do |row|
        row.chomp.split("\t").each do |w|
            h[ w ] += 1
        end
    end
    h.sort{|a,b| b[1]<=>a[1] }.each{|x,y| print "#{x}:#{y}\n" }
end


답변