我看到这个问题,我想做类似的事情:如果列中的值发生变化则打印行
本质上,我将有一个像这样的(制表符分隔的)文件
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