我在一个文件中多次出现以下序列:
yyyy
xxxx
zzzz
我有一个匹配的正则表达式xxxx
。每当有匹配时,我想删除该行,之前的行(例如yyyy
)和之后的行(例如zzzz
)。我怎样才能使用 sed 来做到这一点?
诀窍是存储在“保持空间”中看到的最后一行。
sed -n '
/^xxxx/{n
n
x
d
}
x
1d
p
${x
p
}
' <input file>
从x
- 将当前输入行与保留空间 ( x
) 交换,然后对于第一行不打印任何内容 ( 1d
),后续行打印刚刚从保留空间交换的行 ( p
),在最后一行交换保留再次空格并打印其中的内容($x{x p}
。当我们击中目标行(开始)时要做什么/^xxxx/
- 将接下来的两行读入模式空间(n n
)并将模式空间与保持空间交换(x
) - 这会留下我们想要打印的下一行的保持空间和匹配前一行的模式空间,我们不想要,所以我们放弃它(d
)
这就是我在 perl 中的做法,也许它可以帮助你走上正确的轨道……祝你好运!
open(INFILE,"<in.txt");
my(@arrayOutBoundData, $skipNextLine)l
for (<INFILE>) {
if (not $skipNextLine) {
if (/^xxxx$/) {
pop(@arrayOutBoundData);
$skipNextLine = 1;
} else {
push(@arrayOutBoundData,$_);
}
}
$skipNextLine = 0
}
open(OUTFILE,">out.txt");
for (@arrayOutBoundData) {
print OUTFILE;
}
(未在此系统上测试没有 perl,请原谅任何过度站点。)
您可以查看此文档。它涵盖了使用sed
多行。
这可能对您有用(GNU sed):
echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D'
a
b
这会在模式空间中保留两行的窗口,如果在第一行或第二行中找到所需的正则表达式,则读取下一行,然后删除所有三行。边缘情况是如果在第一行或最后一行中找到正则表达式,而之前/之后没有行。在这些情况下,只能删除两行。
顺便说一句,这个解决方案可能在 GNU sed 中发现了一个可能的错误。地址的M
标志允许^
和$
元字符在正则表达式中用作零长度标记,用于多行字符串中的行首和行尾。空地址//
重用先前声明的地址。该地址应该是包含多行标志的地址吗?目前它似乎包括标志,即使它没有说明,即
sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file
产生不同(正确)的结果:
sed 'N;/^xxxx/M{//d;$!N;d};P;D' file
ifxxxx
出现在文件的第二行。
您可以使用以下内容:
sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}'
这将用一个空行替换 3 行。
您可以先反转文件,使用sed
删除匹配的行和下一行(或行,+Nd
在sed
命令中),最后将结果反转回来:
tac old.file | sed -e '/xxxx/,+1d' | tac > new.file
grep -v -f <(grep -1 "xxxx" file) file