각 행의 숫자와 고유 숫자를 계산하고 요약하는 스크립트

각 행의 숫자와 고유 숫자를 계산하고 요약하는 스크립트
timestamp : IDs returned
20160420084726:-
20160420085418:[111783178, 111557953, 111646835, 111413356, 111412662, 105618372, 111413557]
20160420085418:[111413432, 111633904, 111783198, 111792767, 111557948, 111413225, 111413281]
20160420085418:[111413432, 111633904, 111783198, 111792767, 111557948, 111413225, 111413281]
20160420085522:[111344871, 111394583, 111295547, 111379566, 111352520]
20160420090022:[111344871, 111394583, 111295547, 111379566, 111352520]

타임스탬프 형식은 YYYYMMDDhhmmss입니다.

· 광고는 대괄호로 묶인 광고 자산 ID의 쉼표로 구분된 목록입니다. 또는 - 광고가 반환되지 않은 경우

하루 중 10분마다 출력하는 스크립트를 작성해야 합니다.

  1. 반환된 ID 수

  2. 반환된 고유 ID 수

  3. 스크립트는 고유 ID 또는 전체 ID를 제공해야 하는지 여부를 선택하는 명령줄 매개변수를 지원해야 합니다.

위의 로그 발췌를 사용한 출력 예(총계 모드):

20160420084:0
20160420085:26
20160420090:5

고유 계산 모드에서는 다음을 제공합니다.

20160420084:0
20160420085:19
20160420090:5

이것이 내가 지금까지 가지고 있는 것입니다:

#!/usr/bin/bash
awk -F":" ' { print $1":" $2 } ' file.log | sort -r | uniq -c

결과:

1 20160420090022:[111344871, 111394583, 111295547, 111379566, 111352520] 
1 20160420085522:[111344871, 111394583, 111295547, 111379566, 111352520] 
1 20160420085418:[111783178, 111557953, 111646835, 111413356, 111412662, 105618372, 111413557] 
2 20160420085418:[111413432, 111633904, 111783198, 111792767, 111557948, 111413225, 111413281] 
1 20160420084726:- 
7: –

답변1

배열의 배열을 처리하려면 GNU awk를 사용하십시오( length(array)그러나 현재 대부분의 awk는 이를 수행합니다):

$ cat tst.awk
BEGIN { FS=OFS=":" }
NR>1 {
    time = substr($1,1,11)
    totIds[time] += 0
    if ( gsub(/[][ ]/,"",$2) ) {
        totIds[time] += split($2,ids,/,/)
        for ( i in ids ) {
            unqIds[time][ids[i]]
        }
    }
}
END {
    for ( time in totIds ) {
        print time, ( type ~ /^tot/ ? totIds[time] : length(unqIds[time]) )
    }
}

$ awk -v type='tot' -f tst.awk file
20160420084:0
20160420085:26
20160420090:5

$ awk -v type='unq' -f tst.awk file
20160420084:0
20160420085:19
20160420090:5

GNU awk가 없다면 코드와 메모리 사용량이 약간만 늘어나서 같은 작업을 수행하기 위해 awk를 사용할 수 있습니다.

$ cat tst.awk
BEGIN { FS=OFS=":" }
NR>1 {
    time = substr($1,1,11)
    totIds[time] += 0
    if ( gsub(/[][ ]/,"",$2) ) {
        totIds[time] += split($2,ids,/,/)
        for ( i in ids ) {
            if ( !seen[time,ids[i]]++ ) {
                numUnq[time]++
            }
        }
    }
}
END {
    for ( time in totIds ) {
        print time, ( type ~ /^tot/ ? totIds[time] : numUnq[time]+0 )
    }
}

$ awk -v type='tot' -f tst.awk file
20160420084:0
20160420085:26
20160420090:5

$ awk -v type='unq' -f tst.awk file
20160420084:0
20160420085:19
20160420090:5

답변2

$ cat summarise.pl
#!/usr/bin/perl

use strict;
use List::Util qw(sum0); # useful function to sum elements of array

# handle command-line options
use Getopt::Long qw(VersionMessage :config gnu_getopt);
use Pod::Usage;
$main::VERSION='0.0-alpha';
my $help = 0;
my $type;
GetOptions('total|sum|s|t' => sub { $type .=  't' },
           'unique|u'      => sub { $type .=  'u' },
           'both|b'        => sub { $type  = 'tu' },
           'help|h|?'      => \$help,
           'version|V'     => sub { VersionMessage() },
          ) or pod2usage(2);
pod2usage(-exitval => 0, -verbose => 2) if $help or (! @ARGV && -t);
$type = 'b' if length($type) > 1;
$type = 'u' if length($type) == 0; # default is unique

# Hash-of-Hashes (HoH) to hold timestamps, ids, and id counts.
# Primary key will be timestamp, secondary keys are the IDs,
# and values are the counts of each secondary key.
my %timestamps;

# read and process input file
while(<<>>) {
  next if ($. == 1); # skip first line of input file(s)
  chomp;

  # remove square brackets and spaces from input line
  s/[][]|\s+//g;

  # split current line on colon and commas
  my($ts,@ids) = split /[:,]/;
  $ts = substr($ts,0,11);
  $timestamps{$ts} = () unless (defined $timestamps{$ts});

  # remove non-numeric elements of @ids array
  @ids = grep { /^\d+$/ } @ids;

  # Convert to the HoH structure.
  map { $timestamps{$ts}{$_}++ } @ids;

  close(ARGV) if eof; # reset line counter $. at end of each input file
}

# all input has been processed, so print the results.
foreach my $ts (sort keys %timestamps) {
  my $u = scalar keys %{ $timestamps{$ts} };
  my $s = sum0 values %{ $timestamps{$ts} };

  if ($type eq 'u') {
    printf "%s: %i\n", $ts, $u;
  } elsif ($type eq 't') {
    printf "%s: %i\n", $ts, $s;
  } elsif ($type eq 'b') {
    printf "%s: %i, %i\n", $ts, $u, $s;
  };
}

__END__

=head1 summarise.pl

Script for counting and summarising Numbers & Unique numbers in each line.

=head1 SYNOPSIS

summarise.pl [options] [file ...]

=head1 OPTIONS

=over

=item B<--total>

print total number of IDs per timestamp

=item B<--unique>

print number of unique IDs per timestamp

=item B<--both>

print both unique and total number of IDs

=item B<--version>

Print script's version and exit

=item B<--help>

Print this help message and exit

=back
=cut

노트:목록::유틸리티,포드::사용법, 그리고Getopt::긴둘 다 핵심 Perl 모듈이며 Perl에 포함되어 있습니다.

perldoc podPerl의 "Plain Old Documentation" 내장 코드 문서가 작동하는 방식에 대한 자세한 내용은 참고자료를 참조하세요. 나는 단지 그 기능의 표면만 긁었을 뿐입니다.

예제 출력:

$ ./summarise.pl input.txt 
20160420084: 0
20160420085: 19
20160420090: 5

$ ./summarise.pl input.txt -t
20160420084: 0
20160420085: 26
20160420090: 5

$ ./summarise.pl input.txt -b
20160420084: 0, 0
20160420085: 19, 26
20160420090: 5, 5

$ ./summarise.pl  --version
./summarise.pl version 0.0-alpha
(Getopt::Long::GetOptions version 2.51; Perl version 5.32.1)

$ ./summarise.pl  --help
summarise.pl
    Script for counting and summarising Numbers & Unique numbers in each
    line.

SYNOPSIS
    summarise.pl [options] [file ...]

OPTIONS
    --total, --sum, -t, -s
        print total number of IDs per timestamp

    --unique, -u
        print number of unique IDs per timestamp

    --both, -b
        print both unique and total number of IDs

    --version, -V
        Print script's version and exit

    --help, -h, -?
        Print this help message and exit

getopt_long()그건 그렇고, C 프로그램에서 사용되는 많은 GNU 함수와 마찬가지로 Perl Getopt::Long모듈은 옵션 약어를 이해합니다. 예를 들어 --uni, --uniq, 등은 또는 와 동일하게 처리됩니다 -un. 약어가 옵션 이름과 명확하게 일치할 만큼 길면 작동합니다.-u--unique


%timestamps그리고 해시 데이터 구조가 "어떻게 생겼는지" 알고 싶다면 :

{
  "20160420084" => undef,
  "20160420085" => { 
     105618372 => 1, 111295547 => 1, 111344871 => 1, 111352520 => 1, 111379566 => 1,
     111394583 => 1, 111412662 => 1, 111413225 => 2, 111413281 => 2, 111413356 => 1,
     111413432 => 2, 111413557 => 1, 111557948 => 2, 111557953 => 1, 111633904 => 2,
     111646835 => 1, 111783178 => 1, 111783198 => 2, 111792767 => 2,
  },
  "20160420090" => {
     111295547 => 1, 111344871 => 1, 111352520 => 1, 111379566 => 1, 111394583 => 1
  },
}

해시의 해시는 각 요소가 해시일 수도 있는 연관 배열("해시")입니다.

perldoc perldscPerl 데이터 구조에 대한 자세한 내용은 참고자료를 참조하세요.

관련 정보