如何透過行簇搜尋檔案然後刪除這些行?

如何透過行簇搜尋檔案然後刪除這些行?

我有一個日誌文件,其中包含重複特徵的清單。例如:

## 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'。這兩個方法的問題在於,第一個方法將刪除所有出現的時間戳,從而刪除多個日誌條目;另一個命令的問題是,如果有兩個或多個條目具有相同的時間和應用程式名稱,則所有符合的條目都將被刪除。

我一直在努力工作但一直失敗的事情是做類似的事情:sed '/12:30\n^.*$\n^.*$\ntest notification\nnotification\nnotify-send/d' /tmp/notification_log。請注意,第二行和第三行可以是任何內容(分別是 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允許您匹配多行,但由於它通常一次處理一行,因此您需要明確地將其他行附加到模式空間。你這樣做N

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

^剩下的就是沒有和錨點的程式碼$。錨點通常分別與「行的開頭」和「行的結尾」相關聯;但sed它們確實是「…弦」。當sed一次處理一行時沒有差別。在我們的例子中,我們絕對應該記住錨點是“......字串”。把它們放在中間是沒有意義的。並不是他們永遠不會匹配任何東西。sed首先不會將它們解釋為錨點,它會將它們解釋為文字^$

字串中間不需要「... of the line」錨點。除最後一行外的任何行都在某個換行符之前結束;任何行,但首先在某個換行符之後開始。所以匹配就夠了\n

也許您嘗試使用錨點來確保.*(這是貪婪的並且可以匹配換行符)不匹配超過一行。就算當^$「…一線」主播,.*也會貪心。考慮一下: 中的模式空間sed在最後一行*之後從不包含換行符號。在我們的例子中,我們知道模式空間最多有六行;我們\n一共使用了五次。這保證了正規表示式的每個片段只能匹配簇中的特定行。

錨仍然可以提供幫助。上述指令可以刪除以notify-send-whatever.結尾的群集。$是防止這種情況的正確方法。除了12:30比賽之外沒有其他時間12:30;但它不同2:30,所以一般來說^也很有用。改進後的命令:

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

* 這並不意味著模式空間的末端永遠不可能有換行符。末尾的換行符表示該字元後面有一行。這是最後一行,而且是空的。且後面沒有換行符,因此「最後一行後沒有換行符」成立。

相關內容