如何添加百分比列

Mar*_*tin 10 awk

我想计算所有行中每行的值百分比,并将其添加为另一列.输入(分隔符是\ t):

1   10      
2   10
3   20
4   40
Run Code Online (Sandbox Code Playgroud)

添加第三列的所需输出显示基于第二列中的值计算的百分比:

1   10   12.50   
2   10   12.50
3   20   25.00
4   40   50.00
Run Code Online (Sandbox Code Playgroud)

我试图自己做,但当我计算所有线的总数时,我不知道如何保持其余的线不变.非常感谢您的帮助!

jay*_*ngh 11

在这里,一步通过 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
Run Code Online (Sandbox Code Playgroud)

更新:如果输出中的tab是必需的,则只需将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
Run Code Online (Sandbox Code Playgroud)

突破模式{action}语句:

  • 第一种模式是NR==FNR.FNR是awk的内置变量,用于跟踪给定文件中的记录数(默认情况下由新行分隔).因此,在我们的案例中,FNR将是4.NR与FNR类似,但它不会重置为0.它继续增长.因此,在我们的案例中,NR将是8.

  • 这种模式仅适用于前4个记录,这正是我们想要的.仔细阅读4条记录后,我们将总数分配给变量a.请注意,我们没有初始化它.在awk我们没有.但是,如果整个第2列为0,这将会中断.所以你可以通过在第二个动作语句中添加一个if语句来处理它,即只有当> 0时才进行除法除了0或者其他什么.

  • next是必要的,因为我们并不真的想要执行第二个模式{action}语句.next告诉awk停止进一步的操作并转到下一条记录.

  • 一旦解析了四个记录,下一个模式{action}就会开始,这非常简单.执行百分比并打印第1列和第2列以及它们旁边的百分比.

注意: 正如注释中提到的@lhf一样,只要您在文件中包含数据集,此单行内容就会起作用.如果通过管道传递数据,它将无法工作.

在评论中,讨论了如何awk one-liner从a pipe而不是a中获取输入file.好吧,我能想到的唯一方法是存储列值array,然后使用它们for loop将每个值与它们的百分比一起吐出.

现在arraysawkassociative和永远不会为了,即拉出阵列的值不会以相同的顺序,因为他们走了进去.因此,如果这是确定的,然后下面的一行应该工作.

[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
Run Code Online (Sandbox Code Playgroud)

为了使它们按顺序排列,您可以将结果传递给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
Run Code Online (Sandbox Code Playgroud)