AWK는 처음 3개 값을 찾습니다.

AWK는 처음 3개 값을 찾습니다.

4개의 열이 있는 대용량 데이터 파일이 있는데, 네 번째 열은 행의 총 값입니다. 처음 세 열에 입력된 처음 세 값을 찾을 수 있어야 합니다. 다음 AWK는 출력을 생성하지만 데이터 파일의 네 번째 열에서 중복 합계를 찾으면 중지됩니다. 누군가 이 AWK에 카운터 루프를 추가하여 올바른 출력을 생성하는 방법을 안내해 줄 수 있습니까?

BEGIN { FS="," }

{
  site=$1
  region=$2
  town=$3
  totcnt=$4+0

  key=site","region","town

  if (totcnt >=max) {
    max=totcnt
    mytot[key]=max
  }
}

END { for (i in mytot) {print i "," mytot[i]} }

매우 감사합니다

답변1

다음 Perl 스크립트는 배열 해시(또는 HoA)라는 데이터 구조를 사용합니다. 해시(%sites)에는 처음 세 필드(사이트, 지역, 도시)에서 파생된 키가 있으며 해시의 각 요소는 해당 특정 키에 대한 모든 합계를 포함하는 배열입니다.

HoA를 작성하기 위해 각 줄을 읽어서 선행 또는 후행 공백을 제거하고 빈 줄을 무시합니다. 또한 주석(문자로 시작하는 모든 것 #)을 무시합니다. 왜냐하면 수행하기 쉽고 텍스트 데이터 파일의 데이터에 주석을 달 수 있는 것이 유용하다고 생각하기 때문입니다.

스크립트는 전체 입력 파일을 읽은 후 각 키에 속하는 배열을 역순으로 정렬하고 각 키의 처음 3개 값만 포함하는 요약 줄을 인쇄합니다.

#!/usr/bin/perl

my %sites=();

while(<>) {
  chomp;
  s/#.*//;        # strip comments #
  s/^\s*|\s*$//g; # strip leading and trailing spaces
  next if (/^$/); # skip blank lines

  my($site,$region,$town,$total) = split /,/;
  my $key = "$site,$region,$town";

  push @{ $sites{$key} }, $total;
}

foreach my $k (sort keys %sites) {
  @{ $sites{$k} } = reverse sort @{ $sites{$k} };
  print $k . ": " . join(", ",@{ $sites{$k}}[0..2] ), "\n";
};

예제 출력:

$ ./jon.pl input.txt
site1,North,Bristol: 996776, 9776, 6776
site2,South,Guildford: 99392, 392, 2392
site2,South,London: 99381, 381, 2381
site3,Central,Birmingham: 992628, 5628, 2628
site3,Wales,Cardiff: 99834, 9834, 834
site3,Wales,Swansea: 991796, 3796, 21796
site5,South,Guildford: 99338, 338, 2338
site5,South,London: 99266, 3266, 266
site5,South,Windsor: 99359, 359, 2359
site5,West,Bristol: 997700, 9700, 7700

input.txt귀하가 제공하고 여러 번 복사한 샘플 데이터와 복사본에서 편집된 합계가 포함됩니다.

출력은 더 보기 좋게 수정하거나 각 합계에 대해 한 줄을 인쇄하도록 쉽게 수정할 수 있습니다(힌트, Join() 대신 배열 요소 [0..2]를 반복하세요).


그건 그렇고, 그것은에서 이와 같은 것을 구현하는 것이 가능 awk하지만 에서 수행하는 것이 훨씬 쉽습니다 perl.

답변2

세 개의 최대값을 유지하려면 두 개의 배열을 사용할 수 있습니다. 각 배열에는 세 개의 요소가 포함되어 있습니다. 하나는 실제 값에 대한 것이고 다른 하나는 관련 키에 대한 것입니다. 이러한 것들은 기밀로 유지되어야 합니다.

BEGIN { FS = "," }

{
    key = sprintf("%s,%s,%s", $1, $2, $3)
    value = $4

    for (i = 1; i <= 3; ++i)
        if (values[i] == "" || values[i] < value) {
            tmp = values[i]
            values[i] = value
            value = tmp

            tmp = keys[i]
            keys[i] = key
            key = tmp
        } else break
}

END {
    for (i = 1; i <= 3; ++i)
        printf("%s,%d\n", keys[i], values[i])
}

이는 두 개의 배열 values과 을 사용합니다 keys. 각 읽은 값( value = $4)에 대해 값을 확인합니다.각 값에 대해values그 어느 것보다 큰지 확인해 보세요. 그렇다면 value"현재 값"( )을 및values[i]저것배열의 값 "거품"입니다. 어레이는 keys어레이와 동기화된 상태로 유지됩니다 values.

시험:

$ cat file
A1,B2,C3,35
A4,B5,C6,607
A7,B8,C9,159
A10,B11,C12,100
A13,B14,C15,116
A16,B17,C18,688
A19,B20,C21,346
A22,B23,C24,277
A25,B26,C27,931
A28,B29,C30,552
A31,B32,C33,605
A34,B35,C36,109
$ awk -f script.awk file
A25,B26,C27,931
A16,B17,C18,688
A4,B5,C6,607

관련 정보