[英]How do I delete a matching line, the line above and the one below it, using sed?
我在文件中多次出現以下序列:
yyyy
xxxx
zzzz
我有一個匹配xxxx
的正則表達式。 每當有匹配時,我想刪除該行,之前的行(例如yyyy
)和之后的行(例如zzzz
)。 我如何使用sed來做到這一點?
訣竅是存儲在“保留空間”中看到的最后一行。
sed -n '
/^xxxx/{n
n
x
d
}
x
1d
p
${x
p
}
' <input file>
從x
- 交換當前輸入行與保持空間( x
),然后對於第一行不打印任何東西( 1d
),后續行打印剛剛從保持空間( p
)交換的行,在最后一行line再次交換hold空間並打印其中的內容( $x{xp}
。當我們點擊目標行時開始做什么(開始/^xxxx/
) - 將下兩行讀入模式空間( nn
)並將模式空間與保持空間( x
)交換 - 這使得我們想要打印的下一行保留空間和匹配前的行的模式空間,這是我們不想要的,所以我們放棄它( d
)
您可以查看此文檔 。 它涵蓋了使用sed
處理多行。
您可以使用以下內容:
sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}'
這將用一個空行代替3行。
你可以先反轉文件,使用sed
刪除匹配的行和下一行(或行, sed
命令中的+Nd
),最后反轉結果:
tac old.file | sed -e '/xxxx/,+1d' | tac > new.file
這就是我在perl中的表現,也許它可以幫助你找到正確的軌道......祝你好運!
open(INFILE,"<in.txt");
my(@arrayOutBoundData, $skipNextLine)l
for (<INFILE>) {
if (not $skipNextLine) {
if (/^xxxx$/) {
pop(@arrayOutBoundData);
$skipNextLine = 1;
} else {
push(@arrayOutBoundData,$_);
}
}
$skipNextLine = 0
}
open(OUTFILE,">out.txt");
for (@arrayOutBoundData) {
print OUTFILE;
}
(未在此系統上測試過沒有perl請原諒任何現場。)
這可能適合你(GNU sed):
echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D'
a
b
這樣可以在模式空間中保留兩行窗口,如果在第一行或第二行中找到所需的正則表達式,則讀取以下行,然后刪除所有三行。 邊緣情況是在前/后沒有行的情況下在第一行或最后一行中找到正則表達式。 在這些情況下,只能刪除兩行。
順便提一下,這個解決方案可能在GNU sed中發現了一個可能的錯誤。 地址的M
標志允許^
和$
元字符在regexp中用作多行字符串中行的起點和終點的零長度標記。 空地址//
重用先前聲明的地址。 該地址應該是包含多行標志的地址嗎? 目前它似乎包括國旗,即使它沒有說明即
sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file
產生不同的(正確的)結果:
sed 'N;/^xxxx/M{//d;$!N;d};P;D' file
如果xxxx
出現在文件的第二行。
grep -v -f <(grep -1 "xxxx" file) file
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.