#bash #shell #sum #ksh
#bash #оболочка #сумма #ksh
Вопрос:
У меня есть файл с тысячами чисел в столбце 1, и каждая последовательность этих чисел связана с одним человеком. Есть ли у кого-нибудь идеи о том, как я могу создать сценарий оболочки для суммирования столбца 1 для этого конкретного человека, например:
John is 10 20 30 50 = 110
Вывод сценария будет следующим: John 110
и так далее и тому подобное..
Я пробовал использовать while, for и т. Д., Но я не могу связать сумму с человеком: (
Пример файла:
10 John
20 John
30 John
50 John
10 Paul
10 Paul
20 Paul
20 Paul
20 Robert
30 Robert
30 Robert
60 Robert
80 Robert
40 Robert
40 Robert
40 Robert
15 Mike
30 Mike
Комментарии:
1. пожалуйста, обновите вопрос, указав ваши дополнительные требования (например, среднее значение) и ожидаемый результат
Ответ №1:
Одно awk
решение, которое выводит средние значения с точностью до 2 знаков после запятой и упорядочивает вывод по имени:
awk '
{ total[$2] =$1
count[$2]
}
END { PROCINFO["sorted_in"]="@ind_str_asc"
for ( i in total )
printf "%-10s ] / %-5d = %5.2fn", i, total[i], count[i], total[i]/count[i]
}
' numbers.dat
Это генерирует:
John 110 / 4 = 27.50
Mike 45 / 2 = 22.50
Paul 60 / 4 = 15.00
Robert 340 / 8 = 42.50
Ответ №2:
awk '{ map[$2] =$1 } END { for (i in map) { print i" "map[i] } }' file
Используя awk, создайте массив с именем в качестве первого индекса и текущим итогом значений для каждого имени. В конце выведите имена и итоговые значения.
Ответ №3:
Большое спасибо Раману, это сработало… вы случайно не знаете, возможно ли выполнить вычисление для одного и того же awk, чтобы получить среднее значение для каждого из них? Например, Джон 10 20 30 50 = 110, 110 / 4 = 27
Ответ №4:
Предположения:
- данные хранятся в файле с именем
numbers.dat
- мы будем хранить итоговые значения и подсчеты в массивах, но вычислять средние значения просто для отображения (OP может решить, следует ли также сохранять средние значения в массиве)
Одно bash
из решений, использующее пару ассоциативных массивов для отслеживания наших чисел:
unset total count
declare -A total count
while read -r number name
do
(( total[${name}] = $number))
(( count[${name}] ))
done < numbers.dat
typeset -p total count
Это генерирует:
declare -A total=([Mike]="45" [Robert]="340" [John]="110" [Paul]="60" )
declare -A count=([Mike]="2" [Robert]="8" [John]="4" [Paul]="4" )
Если нам нужны средние значения на основе целых чисел (т. Е. Без десятичных знаков):
for i in ${!total[@]}
do
printf "%-10s ] / %-5d = ]n" "${i}" "${total[${i}]}" "${count[${i}]}" $(( ${total[${i}]} / ${count[${i}]} ))
done
Это генерирует:
Mike 45 / 2 = 22
Robert 340 / 8 = 42
John 110 / 4 = 27
Paul 60 / 4 = 15
Если мы хотим, чтобы средние значения включали, скажем, 2 знака после запятой:
for i in ${!total[@]}
do
printf "%-10s ] / %-5d = %5.2fn" "${i}" "${total[${i}]}" "${count[${i}]}" $( bc <<< "scale=2;${total[${i}]} / ${count[${i}]}" )
done
Это генерирует:
Mike 45 / 2 = 22.50
Robert 340 / 8 = 42.50
John 110 / 4 = 27.50
Paul 60 / 4 = 15.00
Выходные данные отсортированы по имени:
for i in ${!total[@]}
do
printf "%-10s ] / %-5d = %5.2fn" "${i}" "${total[${i}]}" "${count[${i}]}" $( bc <<< "scale=2;${total[${i}]} / ${count[${i}]}" )
done | sort
Это генерирует:
John 110 / 4 = 27.50
Mike 45 / 2 = 22.50
Paul 60 / 4 = 15.00
Robert 340 / 8 = 42.50