如何grep除匹配項和上一行之外的所有內容
我有一個文本文件,並且我有一個不希望 grep 匹配的模式。問題是,我也希望之前的行不匹配。
我的文件:
line 1 line 2 pattern line 4
我試過
cat file | grep -v pattern
了,它輸出:line 1 line 2 line 4
然後我嘗試
cat file | grep -B 1 pattern
了,它輸出:line 2 pattern
但是,當我同時使用它們時
cat file | grep -v -B 1 pattern
,我得到:line 2
我怎樣才能使輸出為:
line 1 line 4
我傾向於只在
grep
從文件中提取單行時使用,所以當我需要在文本中執行更複雜的編輯時,我會使用其他工具。這裡的所有解決方案都假定該模式可能在文本中出現多次,並將刪除出現該模式的行和緊接在它們之前的行。如果模式在連續行上匹配,前兩個解決方案將出現問題。
您可以使用
sed
匹配模式/pattern/
並讓其觸發命令N
andd
,它將下一行附加到緩衝區,然後丟棄兩者:sed '/pattern/ { N; d; }' file
由於您想丟棄模式匹配之前的行,因此我們將數據向後饋入
sed
,從最後一行開始並移至文件的開頭。然後我們在sed
完成後再次反轉數據。tac file | sed '/pattern/ { N; d; }' | tac
該
tac
實用程序是 GNU coreutils 的一部分。如果模式匹配兩個連續的行,這將無法刪除第一行之前的行(因為第一行將被刪除)。
使用
ed
編輯器:printf '%s\n' 'g/pattern/ -1,. d' ,p Q | ed -s file
這會將命令應用於
g/pattern/ -1,. d
文件的內容。此命令搜尋與 匹配的每一行,pattern
然後刪除該行及其之前的行。最終
,p
和Q
編輯命令列印整個文件並退出編輯器而不保存。如果模式匹配兩個連續的行,這將在刪除第一行之前的行之後刪除成為第二行之前的行。
(最後一句我寫的時候是對的,但顯然是只寫句。)
我們還可以使用
grep
它的非標準但通常實現-B
的選項來為我們提供需要刪除的行號。這些數字可以轉換為sed
我們在原始數據上執行的腳本:grep -n -B1 'pattern' file | sed 's/[:-].*/d/' | sed -f /dev/stdin file
給定問題中的文本,該
grep
命令將輸出2-line 2 3:pattern
…並且第一個
sed
命令將其轉換為sed
編輯命令2d
,然後是3d
(“刪除第 2 行和第 3 行”)。管道中的最後一個sed
命令採用此編輯腳本並將其應用於原始文本。這個變體對於匹配模式的連續行沒有問題,因為它使用一種 2-pass 方法,首先找到所有應該刪除的行,然後刪除它們(而不是在第一次閱讀文本時刪除行)。