带条件打印交替行

带条件打印交替行

仍在与混乱的日志文件作斗争。我想要的是找到首先匹配字符串 X 然后匹配字符串 Y 的行。然后我想将它们一起打印。问题是,有时有X,但没有Y。

输入示例

31 X
32 Y
33 X
34 Y
35 X
36 X
37 Y
38 X
39 X

预期产出

31 X
32 Y
33 X
34 Y
36 X
37 Y

因此,第 35、38 和 39 行被省略,因为没有字符串 Y。

我的出发点是这样的:

cat $filename | grep -E X\|Y | grep -A1 'X'

但这并没有过滤掉第 35、38 和 39 行。我想要的是一个条件:如果有 Y,则仅打印 X 行,然后打印 Y 行。如果没有,则不打印任何内容。

答案1

使用sed

sed -n ':b /X/ { h; n; /Y/! b b; H; x; p; }'

输出:

31 X
32 Y
33 X
34 Y
36 X
37 Y

答案2

其他sed

$ sed -e '/X/{
    $!N
    /\n.*Y/!D
}' file
31 X
32 Y
33 X
34 Y
36 X
37 Y

答案3

有多种工具可以做到这一点。如果你有pcregrep(它应该在你的发行版的存储库中可用),你可以这样做:

$ pcregrep -M 'X\n[^\n]+Y' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y

-M开关允许模式匹配换行符,并且正则表达式匹配X,后跟换行符,然后是任何非换行符和Y


另一种选择是编写一个小脚本,如果上一行匹配,则保存上一行,如果X当前行匹配,则将其与当前行一起打印Y。例如,在awk

$ awk '{if(last~/X/ && /Y/){print last"\n"$0}last=$0}' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y

或者 Perl:

$ perl -ne '$last=~/X/ && /Y/ && print "$last$_"; $last=$_' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y

答案4

由于问题被标记为awk

$ awk 'p2 == "X" && $2 == "Y" { print p; print } { p = $0; p2 = $2 }' file
31 X
32 Y
33 X
34 Y
36 X
37 Y

这将打印一行X和紧随其后的Y一行(如果有的话)(或者两者都不会被打印)。

变量pp2分别保存未修改的前一行及其第二列。

相关内容