最初の行をラベルとして定期的に新しいテキストブロックを追加するログファイルがあります。すべてのタグは+で始まります。ブロックには終了モードはありません。各ブロックは、1行でも複数行でも構いません。
+numbers
23
-87
12
+letters
b
w
a
q
+sentences
line of text
another line of text
+numbers
2
34
+address
line1
line2
line3
+numbers
4
87
与えられたタグで始まるすべてのブロックを印刷したいです。たとえば、+数字について見たいものは次のとおりです。
+numbers
23
-87
12
+numbers
2
34
+numbers
4
87
または+アドレスの場合:
+address
line1
line2
line3
awkを使用してこれを行うことができます。しかし、私はsedソリューションを探しています。
答え1
次のいずれかを使用してこれを実行できますsed
(空白行、連続ブロックなど、すべての入力に対して機能する必要があります+numbers
)。
sed -e '/^+/!{H;$!d;}' -e 'x;/^+numbers/!d' logfile
仕組み:
sed '/^+/!{ # if a line doesn't start with a + (so, not a tag)
H # append it to hold space and then,
$!d # if it's not the last line, delete it (that is, get a
} # new input line and restart the cycle);
x # otherwise, exchange buffers and
/^+numbers/!d' # if the pattern space doesn't match "^+numbers", delete it
logfile
つまり、「表示された」行は実行時に保持バッファに格納され、ブロックの残りの行x
は実行時に追加されます。H
次の「表示された」行がパターン空間(または最後の行)に入ると、バッファは再び置き換えられるため、パターン空間には完全な行ブロックが含まれるようになりました。次に始めるのは自動印刷の問題です。+numbers
答え2
2つのGNUがありますsed
。
前提条件:ログファイルに空白行が含まれていません。
sed 's/^+/\n&/' logfile | sed -n '/+numbers/,/^$/{ /^$/d; p }'
出力:
+数字 二十三 -87 12 +数字 2 34 +数字 4 87
バラよりman sed
答え3
tag=address
sed -n "/^+${tag}/,/^+/ {/^[^+]/p; /^+${tag}/p; }" file
これ〜するファイルに同じタグを持つ連続ブロックが含まれていると中断されます。範囲終了正規表現は、次のブロックのタグを使用します。
比較すると、この場合 awk コマンドは中断されません。
awk -v tag=address '/^\+/ {p = $0 ~ "\\+" tag "$"} p' file
awk -v tag=numbers -v RS='+' '$1 == tag {printf "+%s", $0}' file