非固定列数逐行算术计算

非固定列数逐行算术计算

我有一个具有非固定列号的输入文件,我想对其进行一些算术计算:

input.txt
ID1    4651455    234     4651765    392     4652423      470
ID2    16181020   176    16184958    869     16185889     347    16187777     231

输入文件具有制表符分隔的字段,该ID字段在列中始终是唯一的$1(不重复)。并非所有行都具有相同的列数。

我想要实现的是一个制表符分隔的文件,如下所示:

 output1.txt
 ID1     76    266   
 ID2     3762   62   1541  

基本上它会打印$1原始文件的,然后从文件的第二个偶数列开始($4)并减去前两列的值($4- $3- $2),然后对输入文件的所有偶数列执行相同的操作(例如,$6- $5- $4; $8- $7- $6; ...)。据我所知,这可以通过 来完成awk print,但我只知道当我的文件每行都有固定数量的列时如何处理它。

满足我的需求的更理想的输出如下:

output2.txt
ID1    234    76    392    266   470
ID2    176   3762   869    62    347   1541  231

基本上它会打印$1原始文件的 ,然后将输入文件中的奇数列交错打印到列中,如output1.txt.

答案1

$ awk -v OFS='\t' -f script.awk file
ID1     76      266
ID2     3762    62      1541

哪里script.awk

{ printf("%s", $1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, $i - $(i-1) - $(i-2)) } }
{ printf("%s", RS) }

将对文件的每一行输入执行所有块。

第一个块输出 ID。

第二个块按照您的描述迭代字段,并输出由OFS(输出字段分隔符,设置为命令行上的选项卡)分隔的数据。

最后一个块只是输出记录分隔符RS,默认情况下是换行符。

或者,

BEGIN { OFS = "\t" }
{ printf("%s", $1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, $i - $(i-1) - $(i-2)) } }
{ printf("%s", RS) }

摆脱对 的需要-v OFS='\t'

作为“一行”:

$ awk 'BEGIN { OFS = "\t" }
{ printf("%s", $1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d", OFS, $i - $(i-1) - $(i-2)) } }
{ printf("%s", RS) }' file

对于扩展问题:

{ printf("%s", $1) }
{ for (i=4; i<=NF; i+=2) { printf("%s%d%s%d", OFS, $(i-1), OFS, $i - $(i-1) - $(i-2)) } }
{ printf("%s%d%s%s", OFS, $NF, OFS, RS) }

这将直接从原始文件生成以下内容:

ID1     234     76      392     266     470
ID2     176     3762    869     62      347     1541    231

答案2

awk解决方案:

awk '{ r=$1; for(i=4;i<=NF;i+=2) r=r"\t"$i-$(i-1)-$(i-2); printf "%s\n",r }' OFS='\t' file
  • r=$1- 捕获第一个字段

  • for(i=4;i<=NF;i+=2)- 迭代甚至字段

  • $i-$(i-1)-$(i-2)- 执行所需的减法


输出:

ID1 76  266
ID2 3762    62  1541

相关内容