sed:如何删除文件中的第二个匹配项 [英] sed: How to delete second match in a file

查看:119
本文介绍了sed:如何删除文件中的第二个匹配项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个看起来像这样的文件(伪代码):

I have a file that's looking like this (pseudocode):

---
foo: bar
bar: baz
---
baz: quz
---
Some text
Some text
Some text

我需要删除 second --- 行,仅此而已.我知道 sed 可以做到这一点,但我从来没有能够从我能找到的任何 sed 文档中得出正面或反面...

I need to delete the second --- row, and only that. I know that sed can do this, but I have never been able to make heads nor tails out of any sed documentation I could find...

推荐答案

使用 sed 最简单的方法是首先将整个文件读入模式空间并进行处理:

With sed the easiest way would be to first read the whole file into the pattern space and work on that:

sed ':a $!{N; ba}; s/\(^\|\n\)---\n/\n/2' filename

这样做

:a                       # jump label for looping
$!{                      # if the end of input is not reached
  N                      # fetch the next line, append it to the pattern space
  ba                     # go back to :a
}                        # after this, the whole file is in the pattern space.
s/\(^\|\n\)---\n/\n/2    # then: remove the second occurrence of a line that
                         # consists only of ---

@mklement0 指出 \| 仅适用于 GNU sed.一种解决这个问题的方法,因为 \| 只需要捕获第一行中的 ---,将是

@mklement0 points out that the \| only works with GNU sed. A way to work around that, since the \| is only necessary to catch --- in the first line, would be

sed ':a $!{ N; ba; }; s/^/\n/; s/\n---\n/\n/2; s/^\n//' filename

这样做:

:a $!{ N; ba; }  # read file into the pattern space
s/^/\n/          # insert a newline before the first line
s/\n---\n/\n/2   # replace the second occurrence of \n---\n with \n
s/\n//           # remove the newline we put in at the beginning.

这样,第一行就不再是特例了.

This way, the first line is no longer a special case.

如果不将整个文件读入缓冲区,就必须从字符构造一个计数器:

Without reading the whole file into a buffer, you'll have to construct a counter from characters:

sed '/^---$/ { x; s/.*/&_/; /^__$/ { x; d; }; x; }' filename

即:

/^---$/ {    # if a line is ---
  x          # exchange pattern space and hold buffer
  s/.*/&_/   # append a _ to what was the hold buffer
  /^__$/ {   # if there are exactly two in them
    x        # swap back
    d        # delete the line
  }
  x          # otherwise just swap back.
}

...或者只是使用 awk:

...or just use awk:

awk '!/^---$/ || ++ctr != 2' filename

这篇关于sed:如何删除文件中的第二个匹配项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆