行のクラスターでファイルを検索し、それらの行を削除するにはどうすればよいでしょうか?

行のクラスターでファイルを検索し、それらの行を削除するにはどうすればよいでしょうか?

繰り返される特性のリストであるログ ファイルがあります。例:

## This is the pattern of lines
time
urgency
icon_path
summary
body
appname

## Below is what the log file would actually look like
12:30
critical

test notification
notification
notify-send
11:00
low

earlier notification
notification
notify-send
10:46
normal

hello
world
dunstify

私は、検索語に一致する行のブロック/クラスターを検索し、それを bash で削除する方法を見つけようとしています。上記の例でわかるように、行が空の場合もあれば、埋められている場合もあります。これまでに見つけた最良の「解決策」は、 を使用するsed '/12:30/,+5 d'か、それより少し良い方法sed '/12:30/,/notify-send/d'です。これらの両方の問題は、最初のコマンドではタイムスタンプのすべての出現が削除されるため、1 つ以上のログ エントリが削除されることです。もう 1 つのコマンドの問題は、同じ時間と appname を持つエントリが 2 つ以上ある場合、一致するエントリがすべて削除されることです。

私が動作させようとしていて、見事に失敗しているのは、次のようなことですsed '/12:30\n^.*$\n^.*$\ntest notification\nnotification\nnotify-send/d' /tmp/notification_log。2 行目と 3 行目 (それぞれ urgency 行と icon_path 行) は何でも構わないことに注意してください。そのため、私は を使用しました^.*$(率直に言って、それが適切な正規表現であるかどうかさえわかりません)。

編集: 上記の失敗したコマンドを使用すると、出力は次のようになると予想されます。

11:00
low

earlier notification
notification
notify-send
10:46
normal

hello
world
dunstify

そのコマンドの入力は次のとおりです。

12:30
*anything*
*anything*
test notification
notification
notify-send

答え1

すべてのクラスターが M 行の長さで、M が固定され、クラスターが重複せず、クラスターの先頭を検索する必要がない場合は、実際にはそれほど難しくありません。この場合、M は 6 です。

sed複数の行に一致させることができますが、通常は一度に 1 行ずつ処理されるため、パターン スペースに追加の行を明示的に追加する必要があります。これを行うには、次のようにしますN

sed 'N;N;N;N;N; /12:30\n.*\n.*\ntest notification\nnotification\nnotify-send/d'

^残りは、とアンカーのないコードです$。アンカーは、それぞれ「行の先頭」と「行の末尾」に関連付けられることがよくありますが、 では、sed実際には「文字列の…」です。 がsed1 行ずつ処理する場合、違いはありません。この場合、アンカーは「文字列の…」であることを必ず覚えておく必要があります。アンカーを真ん中に置くことは意味がありません。アンカーが何にも一致しないわけではないからです。 は、sedそもそもアンカーとして解釈せず、リテラル^ととして解釈します$

文字列の途中に「… 行」アンカーは必要ありません。最後の行以外の行は、改行文字の直前で終了し、最初の行以外の行は、改行文字の直後で始まります。したがって、 に一致すれば十分です\n

おそらく、アンカー.*(これは貪欲で、改行文字に一致できます) が 1 行以上と一致しないようにしようとしたのでしょう。 と^$「行の…」アンカーとして機能したとしても、.*は貪欲です。次の点を考慮してください。 のパターン スペースには、sed最後の行の後に改行文字が含まれません*。この場合、パターン スペースには最大 6 行あることがわかっており、 を正確に 5 回使用しました\n。これにより、正規表現の各フラグメントがクラスター内の特定の行にのみ一致することが保証されます。

それでもアンカーは役に立ちます。上記のコマンドは、 で終わるクラスターを削除できますnotify-send-whatever。はこれを防ぐ正しい方法です。に一致する$以外に時間はありませんが、 の場合は異なるため、一般にも役立ちます。改善されたコマンド:12:3012:302:30^

sed 'N;N;N;N;N; /^12:30\n.*\n.*\ntest notification\nnotification\nnotify-send$/d'

* これは、パターン スペースの末尾に改行文字が絶対に存在しないという意味ではありません。末尾に改行文字が存在する場合、その文字の直後に行があることを示します。その行は最後の行であり、空です。その後に改行文字は存在しないため、「最後の行の後に改行文字が存在しない」という状態が維持されます。

関連情報