
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
変数に保存しx
、pattern2
一致が発生した場合に印刷します。前に空白行があるとpattern2
空白行が印刷されpattern1
、これが望ましくないかどうかを検出するにはより多くのロジックが必要です。入力の終わりが前に来pattern1
ないすべての末尾aは削除されます。pattern2
答え2
@thrigの答えは素晴らしいですが、いくつかの追加のテストケースを処理するためにいくつかの修正をしました。次のスクリプト:
pattern2
最初に発生する前に発生すると、空白行は印刷されませんpattern1
。pattern2
afterが複数回発生すると、重複した行は印刷されません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
呼び出し:
元の入力ファイルと
^pattern1=
一致する行のみを抽出します。^pattern2$
grep -e '^pattern1=' -e '^pattern2$' file
一致する行
^pattern2$
と直前の行を取得します(非標準-B
オプションを使用)。grep -B1 '^pattern2$'
一致するすべての行を取得します
^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
現在行が
pattern1
行の場合は、予約済みスペースに保存して破棄します。現在行が
pattern2
行の場合は、予約済みスペースを置き換えます。現在の行が現在の行でない場合は
pattern1
削除されます。(暗黙的)現在の行を印刷します。前のコマンドを使用すると、現在の行は検索行のために予約されたスペース
pattern1
でpattern2
置き換えられた行でなければなりません。したがって、スペースを予約すると、必ず行が予約されるため、pattern2
そのpattern1
行は何度も出力されません。
答え4
egrep "^pattern1|^pattern2" <file> | grep -B 1 "^pattern2" | grep "^pattern1"
最初のegrepは、2つのパターンのうちの1つを含む行のみを取得します(出力から不明な他の行はすべて削除)。 2番目のgrepは、Pattern2とその前のすべての行を取得します。これは、パターン1がないパターン2を持つ行を削除するために使用されます。 3 番目の grep は残りの Pattern1 行のみを返します。