sed -e '/XXXX/,+4d' fv.out
我必須在文件中找到特定的模式,並且同時刪除上面的5行和下面的4行。我發現上面的那一行刪除了包含模式和它下面四行的行。刪除相對於包含模式的行的n1個之前的行和n2行
sed -e '/XXXX/,~5d' fv.out
在sed手冊中給出〜表示模式後面的行。但是當我嘗試它時,它是被刪除的模式之後的行。
那麼,如何刪除上面5行和下面同時包含該模式的行下面4行?
sed -e '/XXXX/,+4d' fv.out
我必須在文件中找到特定的模式,並且同時刪除上面的5行和下面的4行。我發現上面的那一行刪除了包含模式和它下面四行的行。刪除相對於包含模式的行的n1個之前的行和n2行
sed -e '/XXXX/,~5d' fv.out
在sed手冊中給出〜表示模式後面的行。但是當我嘗試它時,它是被刪除的模式之後的行。
那麼,如何刪除上面5行和下面同時包含該模式的行下面4行?
一個使用sed
,假設模式無法關閉對方的方式:
script.sed
:
## If line doesn't match the pattern...
/pattern/ ! {
## Append line to 'hold space'.
H
## Copy content of 'hold space' to 'pattern space' to work with it.
g
## If there are more than 5 lines saved, print and remove the first
## one. It's like a FIFO.
/\(\n[^\n]*\)\{6\}/ {
## Delete the first '\n' automatically added by previous 'H' command.
s/^\n//
## Print until first '\n'.
P
## Delete data printed just before.
s/[^\n]*//
## Save updated content to 'hold space'.
h
}
### Added to fix an error pointed out by potong in comments.
### =======================================================
## If last line, print lines left in 'hold space'.
$ {
x
s/^\n//
p
}
### =======================================================
## Read next line.
b
}
## If line matches the pattern...
/pattern/ {
## Remove all content of 'hold space'. It has the five previous
## lines, which won't be printed.
x
s/^.*$//
x
## Read next four lines and append them to 'pattern space'.
N ; N ; N ; N
## Delete all.
s/^.*$//
}
運行,如:
sed -nf script.sed infile
這個想法是讀取5行而不打印它們。如果您發現該圖案,請刪除未打印的線條和下面四行。如果沒有找到圖案,請記住當前行並打印第一條未打印線。最後,打印什麼是未打印的。
sed -n -e '/XXXX/,+4{x;s/.*//;x;d}' -e '1,5H' -e '6,${H;g;s/\n//;P;s/[^\n]*//;h}' -e '${g;s/\n//;p;d}' fv.out
當然,這隻有在文件中出現一次模式時纔有效。如果你有很多,你需要在找到你的模式後閱讀5個新行,如果你再次在這些行中有你的模式,它會變得複雜。在這種情況下,我認爲sed不是正確的工具。
感謝。它在第一次發生時有效。但是,我有很多這種模式。可能是我必須把它放在一個循環中,這樣grep纔不會再出現該模式。除了使用sed以外,你還有什麼建議? – 2012-02-25 11:25:16
我正在研究awk解決方案。在我看來,它更好,因爲更容易理解和維護。 – jfg956 2012-02-25 11:54:31
這可能會爲你工作:
sed 'H;$!d;g;s/\([^\n]*\n\)\{5\}[^\n]*PATTERN\([^\n]*\n\)\{5\}//g;s/.//' file
或該:
awk --posix -vORS='' -vRS='([^\n]*\n){5}[^\n]*PATTERN([^\n]*\n){5}' 1 file
更有效的SED溶液:
sed ':a;/PATTERN/,+4d;/\([^\n]*\n\)\{5\}/{P;D};$q;N;ba' file
謝謝。它完美的作品。但是,我有一些巨大的文件,它佔用了很多時間。 – 2012-02-25 12:54:37
@PopulationXplosive我已經添加了一個awk解決方案。它可能會更快。 – potong 2012-02-25 19:26:19
謝謝。 awk解決方案也佔用大量時間。但新的sed解決方案相當快速。真的很不錯。 – 2012-02-27 10:21:08
的溶液使用awk
:
awk '$0 ~ "XXXX" { lines2del = 5; nlines = 0; }
nlines == 5 { print lines[NR%5]; nlines-- }
lines2del == 0 { lines[NR%5] = $0; nlines++ }
lines2del > 0 { lines2del-- }
END { while (nlines-- > 0) { print lines[(NR - nlines) % 5] } }' fv.out
更新:
這是SC ript解釋:
lines
的最後5行使用旋轉索引(NR%5; NR是創紀錄的數字;在這種情況下線)。$0 ~ "XXXX
; $0
是當前記錄:在這種情況下的直線;作爲擴展正則表達式匹配運算符和~
),我重新閱讀和記行數我有5行刪除(包括當前行)。我的腳本的原始版本是下面的,但我結束了它優化到以上版本:
awk '$0 ~ "XXXX" { lines2del = 5; nlines = 0; }
lines2del == 0 && nlines == 5 { print lines[NR%5]; lines[NR%5] }
lines2del == 0 && nlines < 5 { lines[NR%5] = $0; nlines++ }
lines2del > 0 { lines2del-- }
END { while (nlines-- > 0) { print lines[(NR - nlines) % 5] } }' fv.out
awk
是一個偉大的工具!我強烈建議你在網上找到一個教程並閱讀它。一個重要的事情:awk
與擴展正則表達式(ERE)的作品。其語法是標準正則表達式(RE)在sed
使用略有不同,但都可以用稀土做可以與ERE完成。
謝謝。這是工作。但是,我是awk的絕對初學者。那麼,你能解釋一下腳本嗎?另外,你如何分別修復n1和n2?在我看來,在這裏你已經取得了n1 = n2。 – 2012-02-25 12:54:00
我不明白你的n1/n2問題。解釋腳本是非常前沿的,我正在更新這篇文章。 – jfg956 2012-02-25 18:26:49
謝謝。我想知道如何刪除下面4行(n2)模式。因爲我沒有awk的經驗,所以我認爲你把(n2)之後和(n1)之前的行數設爲相同。我非常困惑。我認爲如果我學習了awk也會很棒。 – 2012-02-27 10:40:45
如果你很高興並將結果輸出到一個文件,而不是標準輸出,vim
可以非常有效地做到這一點:
vim -c 'g/pattern/-5,+4d' -c 'w! outfile|q!' infile
或
vim -c 'g/pattern/-5,+4d' -c 'x' infile
編輯就地文件。
謝謝,我正在尋找的東西(我有至少20行分隔的模式發生)。 – 2012-02-25 12:55:56