条件付きで交互に印刷

条件付きで交互に印刷

まだ複雑なログファイルのために問題が発生しています。私が望むのは、最初に文字列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 -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

これにより、1行Xとその直後の行Y(存在する場合)が印刷されます(または両方が印刷されません)。

変数pp2は、変更されていない前の行と2番目の列をそれぞれ保持します。

関連情報