[英]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}
文件分成兩個文件xx00
和xx01
,前者包含您想要的內容。 您可以更改輸出文件的前綴和/或格式。 如果您有多個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.