他のパターンの前に最後に表示されたパターンを特定します。

他のパターンの前に最後に表示されたパターンを特定します。

2種類のパターンを含む巨大なファイルがあります。モード1そしてモード2モード1以前も何度もこのようなことがあったかもしれません。モード2現れる。それぞれの最後の発生を把握したいと思います。モード1それぞれ前にモード2

入力ファイル:

some text
pattern1=1
some lines
pattern1=2
some lines
pattern1=3
some lines
pattern2
some lines
pattern1=4
some lines
pattern1=5
some lines
pattern1=6
some lines
pattern1=7
some lines
pattern2

希望の出力:

pattern1=3
pattern1=7

grep私が試した間の行数を知るときモード2そして前のことモード1:

grep -B400 "pattern2" | grep "pattern1"

ただし、2つのパターン間の行数に関係なく、すべてのファイルで実行できる一意のコマンドが必要です。

答え1

$ awk '/pattern1/{x=$0} /pattern2/{print x}' input
pattern1=3
pattern1=7

一致(完全行)をpattern1変数に保存しxpattern2一致が発生した場合に印刷します。前に空白行があるとpattern2空白行が印刷されpattern1、これが望ましくないかどうかを検出するにはより多くのロジックが必要です。入力の終わりが前に来pattern1ないすべての末尾aは削除されます。pattern2

答え2

@thrigの答えは素晴らしいですが、いくつかの追加のテストケースを処理するためにいくつかの修正をしました。次のスクリプト:

  • pattern2最初に発生する前に発生すると、空白行は印刷されませんpattern1
  • pattern2afterが複数回発生すると、重複した行は印刷されませんpattern1

変更された入力ファイル:

pattern2
some text
pattern1=1
some lines
pattern1=2
some lines
pattern1=3
some lines
pattern2
pattern2
some lines
pattern1=4
some lines
pattern1=5
pattern2
some lines
pattern1=6
some lines
pattern1=7
some lines
pattern2

次のスクリプトは、あなたの記事で説明されているタスクを実行しているように見えます。

$ awk '/pattern1/{x=$0} length(x) && /pattern2/{print x;x=""}' file
pattern1=3
pattern1=5
pattern1=7

答え3

3つのgrep呼び出し:

  1. 元の入力ファイルと^pattern1=一致する行のみを抽出します。^pattern2$

    grep -e '^pattern1=' -e '^pattern2$' file
    
  2. 一致する行^pattern2$と直前の行を取得します(非標準-Bオプションを使用)。

    grep -B1 '^pattern2$'
    
  3. 一致するすべての行を取得します^pattern1=

    grep '^pattern1='
    

すべてを一度に:

grep -e '^pattern1=' -e '^pattern2$' file |
grep -B1 '^pattern2$' |
grep '^pattern1='

これは、次のようなエッジケースを処理します。user000001の返信つまり、pattern2間に行がない行が多い場合は重複した行を出力せず、ファイルpattern1の先頭pattern2にある行に対して空行を生成しません。


使用sed:

sed -e '/^pattern1=/ { h; d; }' \
    -e '/^pattern2$/ x' \
    -e '/^pattern1=/ !d' file
  1. 現在行がpattern1行の場合は、予約済みスペースに保存して破棄します。

  2. 現在行がpattern2行の場合は、予約済みスペースを置き換えます。

  3. 現在の行が現在の行でない場合はpattern1削除されます。

  4. (暗黙的)現在の行を印刷します。前のコマンドを使用すると、現在の行は検索行のために予約されたスペースpattern1pattern2置き換えられた行でなければなりません。したがって、スペースを予約すると、必ず行が予約されるため、pattern2そのpattern1行は何度も出力されません。

答え4

egrep "^pattern1|^pattern2" <file> | grep -B 1 "^pattern2" | grep "^pattern1"

最初のegrepは、2つのパターンのうちの1つを含む行のみを取得します(出力から不明な他の行はすべて削除)。 2番目のgrepは、Pattern2とその前のすべての行を取得します。これは、パターン1がないパターン2を持つ行を削除するために使用されます。 3 番目の grep は残りの Pattern1 行のみを返します。

関連情報