sed:删除上一行

时间:2012-03-09 21:47:40

标签: regex sed

我需要在比赛前删除空行。

所以给出了文件:

random text
more random text






#matchee

我需要匹配模式/ #matchee /,然后删除之前的空白行。

这是我尝试过的 - 没有成功:

sed '/^[ \t]*$/{N;/#matchee.*$/{D;}}' file.txt

我的逻辑:

  • 如果是空行;将下一行追加到模式空间中,产生/空行\ n ... etc /
  • 如果图案空间包含/ #matchee /,则删除到换行符/ #matchee /

基本上/ matchee /是一个必须保持的常量,我需要删除一个额外的 来自/ #matchee /.

分隔的记录文件中每条记录的空白行

这对任何事都没有影响。我是RTFM-ing,D应该删除模式 空间直到换行符。由于N附加换行符加下一行 - 这应该会产生预期的结果....唉......不,不再。这是因为匹配基本上没有(空白)吗?

2 个答案:

答案 0 :(得分:5)

如果存在奇数个空行,您的方法将起作用,但如果存在偶数,则会失败。您的sed脚本是以下循环。

  • 抓住一行 L1 ,并将其添加到模式空间
  • 如果 L1 非空白,请打印;但如果 为空,则:
    • 抓住另一条线 L2 ,然后将其添加到模式空间
    • 如果 L2 包含#matchee,则从模式空间中丢弃 L1
    • 打印模式空间,该模式空间由 L1 L2 组成,或者只包含 L2

您会注意到 L2 始终打印,即使它是空白的,后跟一行包含#matchee的行。它受到以下事实的保护:它紧跟在奇数个空行之后。

编辑添加:要解决上述问题,可以使用:命令创建标签并使用b命令添加内部循环它的“分支”(转到)。这样:

sed '/^[ \t]*$/{: a;N;/#matchee/!P;D;/^[ \t]*$/b a}' file.txt

是以下循环:

  • 抓住一行 L1 ,并将其添加到模式空间
  • 如果 L1 非空白,请打印;但如果 为空,则:
    • 创建标签a←这是一个无操作,只是goto
    • 的地方
    • 抓住另一条线 L2 ,然后将其添加到模式空间
    • 如果 L2 包含#matchee,请打印 L1
    • 从图案空间中丢弃 L1 (无论我们是否打印)
    • 我们现在可以将 L2 视为 L1 ;它是模式空间中唯一的东西
    • 如果重新命名的 L1 为空,goto a

答案 1 :(得分:2)

这可能对您有用:

sed '$!N;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt

如何运作:

sed '$!N;l;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt

N.B。 P打印到第一个换行符,D删除第一个换行符并开始一个新的循环而不读取另一个记录,除非没有换行符,在这种情况下它的行为类似d并读取在一条线上并开始下一个周期。