Ответ 1
Здесь вы идете, один шаг pass шаг awk-решение -
awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
[jaypal:~/Temp] cat file
1 10
2 10
3 20
4 40
[jaypal:~/Temp] awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1 10 12.5
2 10 12.5
3 20 25
4 40 50
Обновление: Если вкладка является обязательной для вывода, просто установите для переменной OFS значение "\ t".
[jaypal:~/Temp] awk -v OFS="\t" 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1 10 12.5
2 10 12.5
3 20 25
4 40 50
Прорыв операторов шаблона {action}:
-
Первый шаблон -
NR==FNR
. FNR - это встроенная переменная awk, которая отслеживает количество записей (по умолчанию разделенных новой строкой) в заданном файле. Таким образом, FNR в нашем случае будет 4. NR похож на FNR, но он не получает reset до 0. Он продолжает расти. Таким образом, NR в нашем случае будет 8. -
Этот шаблон будет действителен только для первых 4 записей, и именно это мы хотим. После просмотра через 4 записи мы присваиваем общее значение переменной
a
. Обратите внимание, что мы не инициализировали его. Вawk
нам этого не нужно. Тем не менее, это сломается, если весь столбец 2 равен 0. Таким образом, вы можете справиться с этим, поставив оператор if во втором операторе действия. Если это деление, только если a > 0 else сказать деление на 0 или что-то еще. -
next
необходимо, потому что мы действительно не хотим, чтобы выполнялся второй оператор {action}.next
указывает awk прекратить дальнейшие действия и перейти к следующей записи. -
После анализа четырех записей начинается следующий шаблон {действие}, который довольно прост. Выполнение процента и печать столбцов 1 и 2 вместе с процентом рядом с ними.
Примечание.. Как указано в комментарии @lhf, этот однострочный лайнер будет работать только до тех пор, пока у вас есть данные, установленные в файле. Он не будет работать, если вы передадите данные через трубу.
В комментариях обсуждается, как сделать этот awk one-liner
ввод данных из pipe
вместо file
. Ну, единственный способ, которым я мог подумать, - сохранить значения столбца в array
, а затем использовать for loop
, чтобы выплюнуть каждое значение вместе с их процентом.
Теперь arrays
в awk
являются associative
и никогда не находятся в порядке, то есть вытягивание значений из массивов не будет в том же порядке, в каком они вошли. Так что если это нормально, лайнер должен работать.
[jaypal:~/Temp] cat file
1 10
2 10
3 20
4 40
[jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}'
2 10 12.5
3 20 25
4 40 50
1 10 12.5
Чтобы привести их в порядок, вы можете передать результат на sort
.
[jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}' | sort -n
1 10 12.5
2 10 12.5
3 20 25
4 40 50