[英]How to delete 5 lines before and 6 lines after pattern match using Sed?
I want to search for a pattern "xxxx" in a file and delete 5 lines before this pattern and 6 lines after this match. 我想在文件中搜索模式“xxxx”并删除此模式前的5行和此匹配后的6行。 How can i do this using Sed?
我怎么能用Sed做到这一点?
This might work for you (GNU sed): 这可能适合你(GNU sed):
sed ':a;N;s/\n/&/5;Ta;/xxxx/!{P;D};:b;N;s/\n/&/11;Tb;d' file
Keep a rolling window of 5 lines and on encountering the specified string add 6 more (11 in total) and delete. 保持一个5行的滚动窗口,并在遇到指定的字符串时再添加6个(总共11个)并删除。
NB This is a barebones
solution and will most probably need tailoring to your specific needs. 注意:这是一个
barebones
解决方案,很可能需要根据您的特定需求进行定制。 Questions such as: what if there are multiple string throughout the file? 问题如:如果整个文件中有多个字符串怎么办? What if the string is within the first five lines or multiple strings are within five lines of each other etc etc etc.
如果字符串在前五行内或多个字符串在彼此的五行之内等等怎么办等等。
Here's one way you could do it using awk. 这是使用awk可以实现的一种方法。 I assume that you also want to delete the line itself and that the file is small enough to fit into memory:
我假设您还想删除该行本身,并且该文件足够小以适应内存:
awk '{a[NR]=$0}/xxxx/{f=NR}END{for(i=1;i<=NR;++i)if(i<f-5||i>f+6)print a[i]}' file
Store every line into the array a
. 将每一行存储到数组
a
。 When the pattern /xxxx/
is matched, save the line number. 当模式
/xxxx/
匹配时,保存行号。 After the whole file has been processed, loop through the array, only printing the lines you want to keep. 处理完整个文件后,遍历数组,只打印要保留的行。
Alternatively, you can use grep to obtain the line number first: 或者,您可以使用grep首先获取行号:
grep -n 'xxxx' file | awk -F: 'NR==FNR{f=$1}NR<f-5||NR>f+6' - file
In both cases, the lines deleted will be surrounding the last line where the pattern is matched. 在这两种情况下,删除的行将围绕模式匹配的最后一行。
A third option would be to use grep to obtain the line number then use sed to delete the lines: 第三种选择是使用grep获取行号,然后使用sed删除行:
line=$(grep -nm1 'xxxx' file | cut -d: -f1)
sed "$((line-5)),$((line+6))d" file
In this case I've also added the -m
switch so grep exits after finding the first match. 在这种情况下,我还添加了
-m
开关,以便在找到第一个匹配后grep退出。
if you know, the line number (what is not difficult to obtain), you can use something like that: 如果你知道,行号(不难获得),你可以使用类似的东西:
filename="test"
start=`expr $curr_line - 5`
end=`expr $curr_line + 6`
sed "${start},${end}d" $filename (optionally sed -i)
of course, you have to remember about additional conditions like start shouldn't be less than 1 and end greater than number of lines in file. 当然,你必须记住其他条件,比如start应该不小于1并且结束大于文件中的行数。
Another - maybe more easy to follow - solution would be to use grep
to find the keyword and the corresponding line: 另一个 - 可能更容易理解 - 解决方案是使用
grep
来查找关键字和相应的行:
grep -n 'KEYWORD' <file>
then use sed
to get the line number only like this: 然后使用
sed
来获取行号,如下所示:
grep -n 'KEYWORD' <file> | sed 's/:.*//'
Now that you have the line number simply use sed
like this: 既然您有行号,只需使用这样的
sed
:
sed -i "$(LINE_START),$(LINE_END) d" <file>
to remove lines before and/or after! 删除之前和/或之后的行! With only the
-i
you will override the <file>
(no backup). 只有
-i
您将覆盖<file>
(无备份)。
A script example could be: 脚本示例可以是:
#!/bin/bash
KEYWORD=$1
LINES_BEFORE=$2
LINES_AFTER=$3
FILE=$4
LINE_NO=$(grep -n $KEYWORD $FILE | sed 's/:.*//' )
echo "Keyword found in line: $LINE_NO"
LINE_START=$(($LINE_NO-$LINES_BEFORE))
LINE_END=$(($LINE_NO+$LINES_AFTER))
echo "Deleting lines $LINE_START to $LINE_END!"
sed -i "$LINE_START,$LINE_END d" $FILE
Please note that this will work only if the keyword is found once! 请注意,只有在找到关键字一次后,这才有效! Adapt the script to your needs!
根据您的需求调整脚本!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.