kin*_*182 2 linux awk text-processing
我比较新,awk所以我有一个关于做除法并将结果打印在新列中的简单问题。例如:
head data
1 13273 . G C 563 5 . 25 128
1 202259 . G T 675 8 . 12 130
1 598934 . C C 756 9 . 17 231
1 634112 . T C 125 1 . 32 89
1 779762 . G A 675 5 . 28 187
Run Code Online (Sandbox Code Playgroud)
我想将第 9 列除以第 10 列并将结果打印在新的第 11 列中,最好将新结果从高到低排序。例如:
1 634112 . T C 125 1 . 32 89 0.360
1 13273 . G C 563 5 . 25 128 0.195
1 779762 . G A 675 5 . 28 187 0.150
1 202259 . G T 675 8 . 12 130 0.092
1 598934 . C C 756 9 . 17 231 0.074
Run Code Online (Sandbox Code Playgroud)
我只知道如何在 R 中做到这一点,但我想学习如何在awk. 谢谢!
就第一个要求而言,awk 非常具有表现力。如果你想要一个第 11 列,你可以发明它并将它设置为等于第 9 列除以第 10 列的结果。
可以在 awk 中进行排序,但是只是通过管道进行排序有点痛苦,所以更容易。column 命令使它更漂亮,仅此而已。
$ awk '{$11 = $9 / $10}1' file | sort -nr -k 11 | column -t
1 634112 . T C 125 1 . 32 89 0.359551
1 13273 . G C 563 5 . 25 128 0.195312
1 779762 . G A 675 5 . 28 187 0.149733
1 202259 . G T 675 8 . 12 130 0.0923077
1 598934 . C C 756 9 . 17 231 0.0735931
Run Code Online (Sandbox Code Playgroud)
如果您的输出需要制表符分隔,您可以设置OFS变量(忘记 column 命令):
$ awk -v OFS='\t' '{$11 = $9 / $10}1' file | sort -nr -k 11
1 634112 . T C 125 1 . 32 89 0.359551
1 13273 . G C 563 5 . 25 128 0.195312
1 779762 . G A 675 5 . 28 187 0.149733
1 202259 . G T 675 8 . 12 130 0.0923077
1 598934 . C C 756 9 . 17 231 0.0735931
Run Code Online (Sandbox Code Playgroud)
最后,您可以使用sprintf在示例输出中格式化最后一列:
$ awk -v OFS='\t' '{$11 = sprintf("%.3f", $9 / $10)}1' file | sort -nr -k 11
1 634112 . T C 125 1 . 32 89 0.360
1 13273 . G C 563 5 . 25 128 0.195
1 779762 . G A 675 5 . 28 187 0.150
1 202259 . G T 675 8 . 12 130 0.092
1 598934 . C C 756 9 . 17 231 0.074
Run Code Online (Sandbox Code Playgroud)
更新:
正如 Ed Morton 在他的回答中所示,三元运算符?:可用于防止被零除。在这里,我在第 11 列中放置了“UND”以表示“未定义”,但当然您可以将其留空或放置一些不同的值。
$ awk -v OFS='\t' '{$11 = ($10 != 0) ? sprintf("%.3f", $9 / $10) : "UND"}1' file | sort -nr -k 11
1 634112 . T C 125 1 . 32 89 0.360
1 13273 . G C 563 5 . 25 128 0.195
1 779762 . G A 675 5 . 28 187 0.150
1 202259 . G T 675 8 . 12 130 0.092
1 598934 . C C 756 9 . 17 0 UND
Run Code Online (Sandbox Code Playgroud)
在某些时候,您可能会认为 awk 程序变得足够复杂,以至于它最好放在自己的文件中,更强调可读性而不是紧凑性。
$ cat div.awk file
BEGIN { OFS="\t"}
{
if ($10 != 0) {
quotient = $9 / $10
$11 = sprintf("%.3f", quotient)
}
else {
$11 = "UND"
}
print
}
$ awk -f div.awk file | sort -nr -k 11
1 634112 . T C 125 1 . 32 89 0.360
1 13273 . G C 563 5 . 25 128 0.195
1 779762 . G A 675 5 . 28 187 0.150
1 202259 . G T 675 8 . 12 130 0.092
1 598934 . C C 756 9 . 17 0 UND
Run Code Online (Sandbox Code Playgroud)