繁体   English   中英

如何使用Sed删除之前的5行和模式匹配之后的6行?

[英]How to delete 5 lines before and 6 lines after pattern match using Sed?

我想在文件中搜索模式“xxxx”并删除此模式前的5行和此匹配后的6行。 我怎么能用Sed做到这一点?

这可能适合你(GNU sed):

sed ':a;N;s/\n/&/5;Ta;/xxxx/!{P;D};:b;N;s/\n/&/11;Tb;d' file

保持一个5行的滚动窗口,并在遇到指定的字符串时再添加6个(总共11个)并删除。

注意:这是一个barebones解决方案,很可能需要根据您的特定需求进行定制。 问题如:如果整个文件中有多个字符串怎么办? 如果字符串在前五行内或多个字符串在彼此的五行之内等等怎么办等等。

这是使用awk可以实现的一种方法。 我假设您还想删除该行本身,并且该文件足够小以适应内存:

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

将每一行存储到数组a 当模式/xxxx/匹配时,保存行号。 处理完整个文件后,遍历数组,只打印要保留的行。

或者,您可以使用grep首先获取行号:

grep -n 'xxxx' file | awk -F: 'NR==FNR{f=$1}NR<f-5||NR>f+6' - file

在这两种情况下,删除的行将围绕模式匹配的最后一行。

第三种选择是使用grep获取行号,然后使用sed删除行:

line=$(grep -nm1 'xxxx' file | cut -d: -f1)
sed "$((line-5)),$((line+6))d" file

在这种情况下,我还添加了-m开关,以便在找到第一个匹配后grep退出。

如果你知道,行号(不难获得),你可以使用类似的东西:

filename="test"
start=`expr $curr_line - 5`
end=`expr $curr_line + 6`

sed "${start},${end}d" $filename (optionally sed -i)

当然,你必须记住其他条件,比如start应该不小于1并且结束大于文件中的行数。

另一个 - 可能更容易理解 - 解决方案是使用grep来查找关键字和相应的行:

grep -n 'KEYWORD' <file>

然后使用sed来获取行号,如下所示:

grep -n 'KEYWORD' <file> | sed 's/:.*//'

既然您有行号,只需使用这样的sed

sed -i "$(LINE_START),$(LINE_END) d" <file>

删除之前和/或之后的行! 只有-i您将覆盖<file> (无备份)。

脚本示例可以是:

#!/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

请注意,只有在找到关键字一次后,这才有效! 根据您的需求调整脚本!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM