如果列更改则打印两行

如果列更改则打印两行

我看到这个问题,我想做类似的事情:如果列中的值发生变化则打印行

本质上,我将有一个像这样的(制表符分隔的)文件

A 0 10 loss
A 10 20 loss
A 20 30 loss
A 30 40 no
A 40 50 no
A 50 60 no
A 60 70 no
A 70 80 gain
...

我想打印第 4 列从(例如)“loss”->“no”或“no”->“gain”变化的两行,因此输出将是

A 20 30 loss
A 30 40 no
A 60 70 no
A 70 80 gain

第 4 列中的值可以是任何值,但我想打印将更改括起来的两行。

这看起来像是我可以用 awk 做的事情,但我不太熟悉它。

答案1

有了awk,你可以这样做:

awk 'BEGIN  { getline; cmp=$4; preline=$0 }
     cmp!=$4{ print preline, $0 } { cmp=$4; preline=$0 }' OFS='\n'  infile
A 20 30 loss
A 30 40 no
A 60 70 no
A 70 80 gain

BEGIN块中,我们读取第一行并将列#4保存在变量named中cmp,并将整行保存到preline;稍后将上一行的第 4 列与当前行的进行比较,如果有更改,则打印preline值和当前行读取的值$0;下一个块只是更新当前行的第 4 列,并将整行再次更新为下一次运行的上一行。

答案2

使用sed品种编辑器,GNU我们可以执行以下操作:

sed -Ee '
    $d;N
    /\s(\S+)\n.*\s\1$/!p
    D
' input.file

我们始终在模式空间中携带两条线 ,N并寻找最后一个字段的转换。一旦我们检测到一个 ,/\s(\S+)\n.*\s\1$/!p我们就会打印整个模式空间。然后,我们D在转换或无转换的情况下删除模式空间的第一部分,因为第一部分的使用在该阶段结束。

控制权转移到 sed 代码的顶部,如果我们还没有到达 eof,我们会再次重复此过程。 Eof 停止操作,$d

输出:

A 20 30 loss
A 30 40 no
A 60 70 no
A 70 80 gain

答案3

为什么不:

$ awk '(NR > 1) && (LAST !~ $4 "$") {print LAST; print $0} {LAST = $0}' file
A 20 30 loss
A 30 40 no
A 60 70 no
A 70 80 gain

相关内容