簡體   English   中英

刪除所有行,在/ pattern /之后開始兩行

[英]Delete all lines, starting two lines after /pattern/

想象一下,我有一個文件如下:

drink
eat
XXX
pizza
blunzn
sushi

我想刪除文件中的所有行,從模式XXX之后的第三行開始,因此結果應如下所示:

drink
eat
XXX
pizza
blunzn

刪除XXX后的所有行很簡單:

sed -e '/XXX/q' -i data.txt

但是,我發現在刪除模式后很難跳過固定數量的行。

到目前為止我想出的最好的是:

 sed -e '/XXX/ { N; N; q }' -i data.txt

有沒有比添加n * N更優雅的東西(想象一下,我想跳過50行)?

我會使用awk,變量n代表匹配/XXX/之后要打印的行數:

awk -v n=2 'seen && !n-- { exit } /XXX/ { seen = 1 } 1' file

在正則表達式匹配之前, seen是未初始化的( ),所以!n--不被評估。 當正則表達式匹配時, seen被設置為true

seen真時&&兩側都被評估,因此每行減少一次n n達到0!n變為 ,因此腳本退出。

最后的1始終為true,因此在腳本退出之前,每行都會打印出來。

對於sed,我只能提出一些有點模糊的東西,需要GNU擴展來解決:

sed '1,/XXX/{/XXX/!b};/XXX/,+2b;d' infile

或者,評論說:

1,/XXX/ {      # From the first line until the pattern
    /XXX/! b   # Print (by skipping all commands), except when on pattern line
}
/XXX/,+2 b     # For pattern line and the following two, print by skipping commands
d              # Don't print line

GNU擴展是/ pattern /,+ N尋址方案。

/XXX/! 需要位以避免兩次打印圖案線。

參數化為模式后的行數:

n=2
sed "1,/XXX/{/XXX/"\!"b};/XXX/,+${n}b;d" infile

需要奇怪的逃避! 防止解釋為歷史擴展命令。

如果輸入文件非常長並且處理(而不是打印)圖案后面的線加上所需的線需要太長時間,我們可以翻轉它而不是默認打印,然后退出:

sed -n '1,/XXX/{/XXX/!{p;b}};/XXX/,+2{p;b};q' infile
n=3
csplit -s data.txt "/XXX/+${n}"
rm xx01

您的結果是xx00 這會將模式XXX (行偏移量${n}文件分成兩個文件xx00xx01 ,前者包含您想要的內容。 您可以更改輸出文件的前綴和/或格式。 如果您有多個XXX ,它將生成更多文件。

這可能適合你(GNU sed):

sed '/pattern/{:a;N;s/\n/&/2;Ta;q}' file

在遇到所需的模式時,循環所需的行然后退出。

對於遵循所需模式的50行,使用:

sed '/pattern/{:a;N;s/\n/&/50;Ta;q}' file

Bash等同於Tom Fenech優雅的awk

n=2
while IFS= read -r line || [[ -n $line ]]; do 
    if [ $seen ] && ! ((n--)); then
        break
    fi
    if [[ "$line" =~ ^XXX ]]; then 
        seen=1
    fi  
    echo "$line"
done <file   >filtered

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM