プロセスの出力を報告するログファイルがあり、両方のパターンの最後の発生からすべての行を抽出したいと思います。
これらのパターンは、次の行に従います。
Summary process started at <datestring>
そして
Summary process finished at <datestring> with return code <num>
他の多くの情報とともに、ファイル全体にこれらのパターンの複数のインスタンスがあります。最後の項目だけを印刷したいです。
以下が利用可能であることを知っています。
sed -n '/StartPattern/,/EndPattern/p' FileName
パターン間の線を把握しましたが、それを取得する方法がわかりません。最後はい。
sed
またはawk
解決策が出るでしょう。
編集する:StartPatterns
multiple EndPattern
。EndPattern
StartPattern
StartPattern
複数の欠落sがある場合は、最後の行から最後の行だけがEndPattern
必要です。StartPattern
EndPattern
- 来ないのは
StartPattern
来てほしいし、その後は早期到着注意があります。EOF
EndPattern
EOF
EOF
答え1
いつでも次のことができます。
tac < fileName | sed '/EndPattern/,$!d;/StartPattern/q' | tac
システムにGNUがない場合はtac
それを使用することもできますtail -r
。
次のようにすることもできます。
awk '
inside {
text = text $0 RS
if (/EndPattern/) inside=0
next
}
/StartPattern/ {
inside = 1
text = $0 RS
}
END {printf "%s", text}' < filename
ただし、これはファイル全体を読み取ることを意味します。
StartPattern
aと次の間に何かがある場合、最後が終わらない場合、またはaと一致する行がある場合は、他の結果が表示されることがあります。StartPattern
EndPattern
StartPattern
EndPattern
StartPattern
EndPattern
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {printf "%s", text}' < filename
tac+sed+tac
(閉じていない末尾のケースを除いて)その方法と同様に機能しますStartPattern
。
最後の項目が編集者が望むものに最も近いようです。警告を追加するには:
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {
printf "%s", text
if (inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
}' < filename
ファイル全体を読み取らないようにするには:
tac < filename | awk '
/StartPattern/ {
printf "%s", $0 RS text
if (!inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
exit
}
/EndPattern/ {inside = 1; text = ""}
{text = $0 RS text}'
移植性注:)/dev/stderr
のための特別なファイルを含むシステム、またはawk
それをエミュレートする実装(たとえばgawk
、mawk
busybox)が必要ですawk
(上記のLinuxの問題を解決しました)。
print ... > "/dev/stderr"
他のシステムではに置き換えることができますprint ... | "cat>&2"
。
答え2
sed
GNUをこのように使うことができます
sed '/START/{:1;$!{/END/!{N;b1};h}};${x;p};d' file
複数行のパターン全体が表示されるたびに、予約済みスペースを上書きしてください。ファイルの末尾に印刷してください。
これは一貫した動作を提供します。
- 同じ行のSTARTとENDはどちらも行と一致します。
- 最初のSTART以降の複数のSTARTは、ENDまですべて一致します。
- END がない場合、一致は印刷されず、START から END までの最後の項目が印刷されます。
答え3
の場合、GNU sed
他の解決策は次のとおりです(変数P1
/をP2
開始/終了パターンとして使用)。
sed -n "/${P1}/,/${P2}/H; /${P1}/h; \${g;p}"
@Stéphane Chazelasのソリューションとの主な違いは次のとおりです。
- 最後のEND / EOFの前に複数のSTARTがある場合は、最後のSTARTから最後のEND / EOFまで表示されます。
- STARTと同じ行にあるすべてのENDは無視されます。
- 最後の入力ラインで最後のENDをサポート
- 最後のSTART以降にENDがない場合は、最後のSTARTからEOFまで印刷します。
答え4
awkの解決策は次のとおりです。
awk '/EndPattern/ {recording=0} recording>0 {buffer=buffer $0 "\n"} /StartPattern/ {recording+=1; buffer=""} END {printf "%s", buffer; if(recording>0) {print "WARNING: missing EndPattern" > "/dev/stderr"}}'
したがって、次の入力の場合:
1
StartPattern
2
3
EndPattern
4
5
StartPattern
6
7
EndPattern
8
以下の結果が出力されます。
6
7
正確な行の一致が必要な場合は、StartPatternを^StartPattern $に置き換え、EndPatternも同様です。入れ子になったパターンを無視するには、Recording+=1 を Recording=1 に置き換えることもできます。