问题 如何使用sed删除匹配的行,上面的行和下面的行?


我在文件中多次出现以下序列:

yyyy
xxxx
zzzz

我有匹配的正则表达式 xxxx。只要有匹配,我想删除该行,即之前的行(例如 yyyy)和它之后的行(例如 zzzz)。我如何使用sed来做到这一点?


7449
2018-05-18 06:19


起源



答案:


诀窍是存储在“保留空间”中看到的最后一行。

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


13
2018-05-20 17:10



使用保持缓冲区“交换”模式空间的'x'命令的进一步说明: grymoire.com/Unix/Sed.html#uh-53 - Ben Lever
我无法运行上面的脚本。它说sed:FUNCTION / ^ pattern / {n n x d} x 1d p $ {x p}无法解析不确定原因? - oortcloud_domicile


答案:


诀窍是存储在“保留空间”中看到的最后一行。

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


13
2018-05-20 17:10



使用保持缓冲区“交换”模式空间的'x'命令的进一步说明: grymoire.com/Unix/Sed.html#uh-53 - Ben Lever
我无法运行上面的脚本。它说sed:FUNCTION / ^ pattern / {n n x d} x 1d p $ {x p}无法解析不确定原因? - oortcloud_domicile


你可以退房 这个文件。它涵盖了使用 sed 使用多行。


1
2018-05-18 06:55





这就是我在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请原谅任何现场。)


0
2018-05-18 06:49





您可以使用以下内容:

sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}'

这将用一个空行代替3行。


0
2017-11-23 13:12





您可以先反转文件,使用 sed 删除匹配的行和下一行(或行, +Nd 在 sed 命令),最后反转结果:

tac old.file | sed -e '/xxxx/,+1d' | tac > new.file

0
2017-07-05 05:03





这可能适合你(GNU sed):

echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D'
a
b

这样可以在模式空间中保留两行窗口,如果在第一行或第二行中找到所需的正则表达式,则读取以下行,然后删除所有三行。边缘情况是在前/后没有行的情况下在第一行或最后一行中找到正则表达式。在这些情况下,只能删除两行。

顺便提一下,这个解决方案可能在GNU sed中发现了一个可能的错误。该 M 地址标志允许 ^ 和 $ 元字符在regexp中用作零长度标记,用于多行字符串中行的开头和结尾。空地址 // 重复使用先前声明的地址。该地址应该是包含多行标志的地址吗?目前它似乎包括国旗,即使没有说明,即

sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file

产生不同的(正确的)结果:

sed 'N;/^xxxx/M{//d;$!N;d};P;D' file

如果 xxxx 出现在文件的第二行。


0
2018-03-16 12:11



几乎,但他希望zzzz也消失。 - Samuel Edwin Ward
@SamuelEdwinWard简单修复见编辑。 - potong


grep -v -f <(grep -1 "xxxx" file) file

-1
2018-03-06 12:02