2016-11-21 2 views
1

Я пытаюсь сделать резюме текстового файла, но есть один поворот, который я не могу сделать. У меня есть несколько строк, и я хочу получить средние значения в последовательных строках из той же категории. Когда меняется категория, я хочу получить новую строку в итоговой сводке.Суммировать значения из текстового файла в bash

Текстовый файл выглядит следующим образом (text.txt):

1 1 a 
2 2 a 
3 3 a 
4 4 b 
5 5 b 
6 6 a 
7 7 a 
8 8 b 

Хорошо, и я хочу, чтобы это (счетчик, категория, средний 1, средний 2):

1 a 2.0 2.0 
1 b 4.5 4.5 
2 a 6.5 6.5 
2 b 8.0 8.0 

у меня до сих пор, но это только суммирует все:

cat test.txt | awk '{avg1+=$1;avg2+=$2;cat=$3;count++}END{print "1",cat,avg1/count,avg2/count} 

Это результат:

1 b 4.5 4.5 

Итак, что я могу сделать, чтобы получить это право? Как понять, что категория меняется? Один лайнер был бы замечательным. Спасибо!

+0

Пожалуйста, отредактируйте свой вопрос, чтобы предоставить нам вход и выход, которые соответствуют - на данный момент похоже, что они не связаны. Что касается решения вашей проблемы, вам нужно изменить 'avg1' и' avg2' на массивы. –

+0

Thx за подсказку, Том, но я думаю, что я представил соответствующие входные и выходные данные в отношении того, что я хочу. Не уверен, если я просто не понимаю, что вы имеете в виду. – cowhi

+0

Сообщение было достаточно документировано для меня, чтобы найти проблему (по крайней мере, я думаю) –

ответ

2

Тег END в AWK выполняется только в конце ввода. Вот почему у вас есть только одна строка. Если вы хотите печатать для каждого изменения, вам нужно проверить, изменилась ли строка и распечатать результат по мере их изменения.

Вы можете использовать этот скрипт, чтобы сделать это:

FNR == 1{ 
    previousChar = $3; 
    round=1; 
} 

{ 
    if (previousChar != $3) { 
     print int((round+1)/2),cat,avg1/count,avg2/count; 
     avg1=0.0; 
     avg2=0.0; 
     count=0; 
     round++; 
     previousChar=$3; 
    } 
    avg1+=$1; 
    avg2+=$2; 
    cat=$3; 
    count++ 
} 

END { 
    print int((round+1)/2),cat,avg1/count,avg2/count 
} 

Вы все еще должны напечатать последний конец в конце тега.

Одним из преимуществ скриптов AWK является то, что вы можете использовать его на одной линии, как это:

cat test.txt | awk 'FNR == 1{previousChar = $3;round=1;}{if (previousChar != $3) {  print int((round+1)/2),cat,avg1/count,avg2/count;avg1=0.0;avg2=0.0;count=0;round++;previousChar=$3;}avg1+=$1;avg2+=$2;cat=$3;count++} END {print int((round+1)/2),cat,avg1/count,avg2/count}' 

Выходной пример с входом:

1 a 2 2 
1 b 4.5 4.5 
2 a 6.5 6.5 
2 b 8 8 

Edit: добавлена ​​версия cowhi

+0

ОК, это уже близко. Спасибо! Теперь мне просто нужно иметь счетчик для каждого коммутатора в основном как в примере результата и поплавках, которые должны быть результатом деления. – cowhi

+0

Хорошо, я понял. Если вы обновите свой ответ тем, чего не хватает, я приму его как лучший ответ: cat test.txt | awk 'FNR == 1 {previousChar = $ 3; round = 1;} {if (previousChar! = $ 3) {print int ((round + 1)/2), cat, avg1/count, avg2/count; avg1 = 0; avg2 = 0; кол = 0; круглый ++; previousChar = $ 3;} avg1 + = $ 1; avg2 + = $ 2; кот = $ 3; count ++} END {print int ((round + 1)/2), cat, avg1/count, avg2/count} ' – cowhi

Смежные вопросы