如何用bash/awk/sed按行根据第6列值修改第5列内容?
问题需求
用bash/awk/sed工具修改多列文档:文档第5列所有行的值均为"A",第6列为递增数字。要求检查每行第6列的值,若大于整数275,则将该行第5列的值改为"B"。
我尝试过的脚本
方法1:while循环
while IFS="" read -r line ; do awk 'BEGIN {FS = " "}' Num=$(awk '{print $6}' original.txt) if [ $Num > 275 ] ; then awk '{ gsub("A","B",$5) }' fi done < original.txt >> edited.txt
方法2:for循环结合cat
awk 'BEGIN {FS = " "}' original.txt Num=$(awk '{print $6}' heterodimer_P49913/unrelaxed_model_1.pdb) integer=275 for data in $Num ; do if [ $data > $integer ] ; then ##Change value in other column to "B" for all lines containing column 6 values greater than "integer" fi done
解决方案
直接用awk一行命令就能完成,无需复杂循环,效率更高:
awk '$6 > 275 { $5 = "B" } 1' original.txt > edited.txt
命令解释
$6 > 275:判断当前行第6列的数值是否大于275(awk会自动将字符串形式的数字转为数值做比较){ $5 = "B" }:满足条件时,将第5列的值设为"B"1:awk中非零值会触发默认动作——打印当前行,因此无论是否满足条件,所有行都会被输出- 默认情况下awk以空白字符(空格/制表符)作为列分隔符,无需额外指定;如果文档用固定分隔符(比如制表符),可添加
-F'\t'参数
原脚本的问题说明
while循环脚本的问题:
- 反复调用
awk '{print $6}' original.txt会读取整个文件的第6列,而非当前行的第6列 [ $Num > 275 ]中的>是重定向符号,会创建名为275的文件,数值比较应使用if (( $Num > 275 ))或if [ $Num -gt 275 ]- 最后一个
awk '{ gsub("A","B",$5) }'没有处理当前行,也未输出结果
- 反复调用
for循环脚本的问题:
- 将所有第6列的值存入变量后循环,无法对应到原文件的具体行,也就无法修改对应行的第5列值
内容的提问来源于stack exchange,提问作者meh47336
相关产品推荐
相关产品推荐

