Как рассчитать среднее значение двух файлов, используя awk и grep - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть 2 следующих файла:

очков:

John,12
Joseph,14
Madison,15
Elijah,14
Theodore,15
Regina,18  

команд:

Theodore,team1
Elijah,team2
Madison,team1
Joseph,team3
Regina,team2
John,team3

Я хотел бы рассчитать средние очки каждой команды.Я придумал решение, используя только 2 awk утверждений.Но я хотел бы сделать это более эффективным способом (без использования for циклов и if операторов).

Вот что я сделал:

#!/bin/bash

awk 'BEGIN { FS="," }
      FNR==NR { a[FNR] = $1; b[FNR] = $2; next } { for(i = 0; i <= NR; ++i) { if(a[i] == $1) print b[i], $2 } }' teams points > output.txt

В этом первомawk команда, я отделяю команды (team1, team2, team3) от имен и создаю новый файл, содержащий только мои команды и соответствующие очки для каждой команды (и поэтому необходимо использовать for loop и if statement).

Во-вторых:

awk 'BEGIN { FS=" "; 
              count_team1 = 0; 
              count_team2 = 0; 
              count_team3 = 0
              average_team1 = 0; 
              average_team2 = 0; 
              average_team3 = 0 } 

        /team1/  { count_team1 = count_team1 + 1; average_team1 = average_team1 + $2 }
        /team2/  { count_team2 = count_team2 + 1; average_team2 = average_team2 + $2 }
        /team3/  { count_team3 = count_team3 + 1; average_team3 = average_team3 + $2 }


      END { print "The average of team1 is: " average_team1 / count_team1;
            print "The average of team2 is: " average_team2 / count_team2; 
            print "The average of team3 is: " average_team3 / count_team3 }' output.txt

В этой второй команде awk я просто создаю переменные для хранения количества членов каждой команды и других переменных, чтобы иметьОбщее количество очков каждой команды.Это легко сделать, поскольку мой новый файл output.txt содержит только команды и результаты.

Это решение работает, но, как я уже говорил, я бы хотел сделать это без использования цикла for иif заявление.Я думал не использовать FNR==NR и использовать grep -f для сопоставления, но я не получил никаких окончательных результатов.

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Дайте попытку этому

awk -F, '
$2 ~ /^[0-9][0-9]*$/ {
  team_sum[team[$1]]+=$2
  team_score_count[team[$1]]++
  next
}
{
  team[$1]=$2
} 
END { 
  for (team_name in team_sum)
    print "The average of " team_name " is " (team_sum[team_name]/team_score_count[team_name])
}' teams points


The average of team1 is 15
The average of team2 is 14
The average of team3 is 13
0 голосов
/ 27 ноября 2018

Как насчет этого простого awk решения, не могли бы вы попробовать следующее.

awk -F, '
FNR==NR{
  a[$1]=$2
  next
}
{
  b[$2]=$1 in a?b[$2]+a[$1]:b[$2]
  c[$2]++
}
END{
  for(i in c){
    print i,b[i]/c[i]
  }
}' points teams

Вывод будет следующим.

team1 15
team2 16
team3 13

Объяснениевышеуказанный код:

awk -F, '                               ##Setting field separator as comma for all lines.
FNR==NR{                                ##Checking condition FNR==NR which will be TRUE when Input_file points is being read.
  a[$1]=$2                              ##Creating an array named a whose index is $1 and value is $2 of current line.
  next                                  ##next keyword will skip all further statements from here.
}
{
  b[$2]=$1 in a?b[$2]+a[$1]:b[$2]       ##Creating array b whose index is $2 which is checking condition if $1 is present in a then add a[$1] to b[$2] value itself.
  c[$2]++                               ##creating an array named c whose index is $2 and increasing its value.
}
END{                                    ##Starting END section of awk command here now.
  for(i in c){                          ##Traversing through array c here in a for loop.
    print i,b[i]/c[i]                   ##printing value of variable i and then printing value of b[i]/c[i] here.
  }                                     ##Closing for loop block here.
}' points teams                         ##Mentioning Input_file names points and teams here.
0 голосов
/ 27 ноября 2018

Использование только awk:

$ awk -F, '
NR==FNR {                 # process teams file
    a[$1]=$2              # hash to a: a[name]=team
    next
}
{                         # process points file
    b[a[$1]]+=$2          # add points to b, index on team: b[team]=pointsum
    c[a[$1]]++            # add count to c, index on team: c[team]=count
}
END {
    for(i in b)           
        print i,b[i]/c[i] # compute average
}' teams points
team1 15
team2 16
team3 13

Редактировать: Решение без цикла for в END:

Если файл команд отсортированв команде вы можете избежать цикла for в END.В качестве бонуса команды выставляются в следующем порядке:

$ awk -F, '
NR==FNR {                # process the points file
    a[$1]=$2             # hash to a on name a[name]=points
    next
}
{                        # process the sorted teams file
    if($2!=p && FNR>1) { # then the team changes
        print p,b/c      # its time to output team name and average
        b=c=0            # reset counters
    }
    c++                  # count 
    b+=a[$1]             # sum of points for the team
    p=$2                 # p stores the team name for testing on the next round
}
END {                    # in the END
    print p,b/c          # print for the last team
}' points <(sort -t, -k2 teams)
team1 15
team2 16
team3 13
...