输入文件是“id number1 number2 count”行,number1和number2都是上升的。
Barcode000000 48521 1855 0
Barcode000001 48621 1855 0
Barcode000002 48721 1855 1
Barcode000003 48821 1855 0
Barcode000004 48921 1955 20
Barcode000005 49021 1955 0
现在我用awk -v bin=100 '{print ($2-48521)/bin" "($3-1855)/bin" "$4}'
.
如何从输入文件的第一行设置48521
和?1855
答案1
通过将它们保存在变量中来记住它们是什么,然后使用这些变量来计算新字段。您可以检测到您正在查看第一条记录(行),因为特殊变量NR
是 1。在下面的代码中,我将数字保存到a
和中b
。
$ awk -v bin=100 'NR == 1 { a = $2; b = $3 } { $2 = ($2 - a)/bin; $3 = ($3 - b)/bin; print }' file
Barcode000000 0 0 0
Barcode000001 1 0 0
Barcode000002 2 0 1
Barcode000003 3 0 0
Barcode000004 4 1 20
Barcode000005 5 1 0
测试之前的块NR == 1
仅针对第一个记录执行,而第二个块没有条件并对所有记录执行。
或者,没有第一个字段(这更接近代码的输出可能的样子):
$ awk -v bin=100 'NR == 1 { a = $2; b = $3 } { print ($2 - a)/bin, ($3 - b)/bin, $4 }' file
0 0 0
1 0 0
2 0 1
3 0 0
4 1 20
5 1 0
请注意,默认的输出字段分隔符是单个空格,因此如果使用逗号分隔输出记录的字段,则无需插入空格。可以通过设置特殊变量的值来更改输出分隔符OFS
。
答案2
使用任何 awk:
$ awk -v bin=100 'NR==1{split($0,a)} {for (i=2;i<=3;i++) $i=($i-a[i])/100} 1' file
Barcode000000 0 0 0
Barcode000001 1 0 0
Barcode000002 2 0 1
Barcode000003 3 0 0
Barcode000004 4 1 20
Barcode000005 5 1 0
或者如果您只想打印一小部分特定字段:
$ awk -v bin=100 'NR==1{split($0,a)} {for (i=2;i<=3;i++) $i=($i-a[i])/100; print $2, $3, $4}' file
0 0 0
1 0 0
2 0 1
3 0 0
4 1 20
5 1 0
或者如果您有很多字段但只是不想打印第一个字段:
$ awk -v bin=100 'NR==1{split($0,a)} {for (i=2;i<=3;i++) $i=($i-a[i])/100; $1=""; sub(OFS,"")} 1' file
0 0 0
1 0 0
2 0 1
3 0 0
4 1 20
5 1 0
答案3
使用磨坊主( mlr
):
$ bin=100
$ mlr --nidx step -a from-first -f 2,3 then put '$2 = ${2_from_first} / '$bin' ; $3 = ${3_from_first}/ '$bin'; unset ${2_from_first}, ${3_from_first}' file
Barcode000000 0 0 0
Barcode000001 1 0 0
Barcode000002 2 0 1
Barcode000003 3 0 0
Barcode000004 4 1 20
Barcode000005 5 1 0
或者,没有第一个字段。
$ bin=100
$ mlr --nidx step -a from-first -f 2,3 then put '$2 = ${2_from_first} / '$bin' ; $3 = ${3_from_first}/ '$bin'; unset $1, ${2_from_first}, ${3_from_first}' file
0 0 0
1 0 0
2 0 1
3 0 0
4 1 20
5 1 0
关于step
子命令来自米勒文档:
计算取决于较早/较晚记录的值,可以选择按类别分组。
from-first 计算字段与第一条记录的差异