Linux 使用awk将列中的值替换为txt文件中的另一个值

Linux 使用awk将列中的值替换为txt文件中的另一个值,linux,bash,awk,Linux,Bash,Awk,我不熟悉linux和awk脚本。我有如下tab delim txt文件: AAA 134 145 Sat 150 167 AAA 156 167 Sat 150 167 AAA 175 187 Sat 150 167 我只想将最后一行第二列(175)中的值替换为最后一行第五列(150+1)中的值,这样我的最终输出应该如下所示 AAA 134 145 Sat 150 167 AAA 156 167 Sat 1

我不熟悉linux和awk脚本。我有如下tab delim txt文件:

AAA   134  145  Sat    150   167
AAA   156  167  Sat    150   167
AAA   175  187  Sat    150   167 
我只想将最后一行第二列(175)中的值替换为最后一行第五列(150+1)中的值,这样我的最终输出应该如下所示

AAA   134  145  Sat    150   167
AAA   156  167  Sat    150   167
AAA   151  187  Sat    150   167

我尝试了
awk'$2=$5+1'file.txt
,但它改变了第二列中我不想要的所有值。我只想用150(+1)替换175。请指导我,困难在于,与sed不同,awk不会告诉我们何时处理最后一行。这里有一个解决方法:

$ awk 'NR>1{print last} {last=$0} END{$0=last;$2=$5+1;print}' OFS='\t' file.txt
AAA     134     145     Sat     150     167
AAA     156     167     Sat     150     167
AAA     151     187     Sat     150     167
这是通过在变量
last
中保留前一行来实现的。更详细地说:

  • NR>1{print last}

    对于除第一行以外的每一行,打印
    last

  • last=$0

    更新
    last
    的值

  • END{$0=last;$2=$5+1;print}

    当我们到达文件末尾时,更新字段2并打印

  • OFS='\t'

    将输出上的字段分隔符设置为选项卡

替代方法 这种方法读取文件两次,第一次计算行数,第二次更改最后一行。因此,这效率较低,但可能更容易理解:

$ awk -v n="$(wc -l <file.txt)" 'NR==n{$2=$5+1} 1' OFS='\t' file.txt
AAA     134     145     Sat     150     167
AAA     156     167     Sat     150     167
AAA     151     187     Sat     150     167
更改第一行和最后一行
@John1024的回答内容丰富

awk
具有内置的
getline
函数来处理文件

成功返回
1
,文件结束返回
0
,错误返回
-1

awk '{ 
        line=$0; 
        if (getline == 0 ) {
           $2=$5+1; 
           print $0; 
        } else { 
           print  line RS $0;
        }
     }' OFS='\t' file.txt

谢谢它很好用。类似地,如果我想更改第一行第二列的值,我该怎么做that@Carol我刚刚在答案中添加了第一行的代码。仅供参考
END{$2=$5+1;print}
依赖于每个POSIX的未定义行为,因此它只能在某些AWK中工作。POSIX仅保证NF仍将使用上次读取记录的值填充在END部分,而不是$0、$1等。如果您愿意,为了便于移植,请从
END{$0=last;…}
@EdMorton开始。答案更新为
$0=last
。我尝试了gawk、mawk和原始awk,但没有明显的问题,但是兼容POSIX更好。谢谢购买阿诺德·罗宾斯的《有效的Awk编程》第四版@约翰1024-FWIW我总是建议人们购买这本书,因为写这本书并提供GNU awk的人应该为他的努力赚几块钱,而不是因为非常友好地将这本书作为PDF提供参考而受到惩罚。请阅读这本书《有效的awk编程》,第四版,通过阿诺德·罗宾斯对awk有一个基本的了解。你过去的几个问题表明,你尝试通过无误的尝试来学习AWK,这是一个糟糕的想法。
$ awk 'NR==1{$2=$5+1} NR>1{print last} {last=$0} END{$0=last;if(NR>1)$2=$5+1;print}' OFS='\t' file.txt
AAA     151     145     Sat     150     167
AAA     156     167     Sat     150     167
AAA     151     187     Sat     150     167
awk '{ 
        line=$0; 
        if (getline == 0 ) {
           $2=$5+1; 
           print $0; 
        } else { 
           print  line RS $0;
        }
     }' OFS='\t' file.txt