我是linux和awk脚本的新手。我有tab delim txt文件,如下所示:
AAA 134 145 Sat 150 167
AAA 156 167 Sat 150 167
AAA 175 187 Sat 150 167
我想用最后一行,第五列(150 + 1)中的值替换最后一行,第二列(175)中的值,以便我的最终输出看起来像
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。请指导我
答案 0 :(得分:3)
难点在于,与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
$ awk 'NR==1{$2=$5+1} 1' OFS='\t' file.txt
AAA 151 145 Sat 150 167
AAA 156 167 Sat 150 167
AAA 175 187 Sat 150 167
$ 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
答案 1 :(得分:2)
@ 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