【问题标题】:How to select lines between two marker patterns which may occur multiple times with awk/sed and delete those lines如何选择可能使用 awk/sed 多次出现的两个标记模式之间的行并删除这些行
【发布时间】:2020-04-04 08:48:33
【问题描述】:

假设一个文件包含:

abc
def1
ghi1
mno
abc
def2
ghi2
jkl2
abc
pqr
stu
mno

起始模式是 abc,结束模式是 mno 所以,我需要输出为:

def2
ghi2
jkl2

即,应删除 abc 和 mno 之间的任何内容,并且我希望打印 abc 之后的任何内容,包括 abc,如果它不是以 mno 结尾的则要打印

我尝试了这个sed '/^abc$/,/^mno$/{//!b};d' file,但它删除了所有行,除了以abcmno 开头的行之间的行。

【问题讨论】:

  • 示例中的第五行是错误的吗?如果是这样,一个简单的sed '/^abc$/,/^mno$/d' file 就可以了。如果不是,请解释为什么abc 不在输出中
  • @Sundeep,先生,如果您不介意的话,我可以告诉您我的想法,输出为def2 ghi2 jkl2,因为就在def2 之前,abc 的出现是没有关闭,后面又跟着abc,恕我直言,这就是 OP 想要打印它的原因,但 OP 只能确认这一点。
  • Re "abc 和 mno 之间的任何东西都应该被删除",您要求保留的行在abcmno 之间...
  • 没有第 5 行不是错误的。我想要 abc 之后的任何东西,包括 abc 如果它不是以 mno 结尾的。
  • @RavinderSingh13,这与我的观点相同。有两个循环,并且包含整个文件。

标签: regex perl awk sed


【解决方案1】:

如果您在abc\n 上拆分输入,您可能会移除那些包含mno 的内容,例如使用 GNU awk:

awk '!/mno/' RS='abc\n' infile
def2
ghi2
jkl2

【讨论】:

  • 这是一个 GNU awk 扩展。在 POSIX awk 中,变量 RS 只能是单个字符。
  • 如果mno 出现在第一个abc 之前,这将失败
  • @kvantour:我明确提到了 GNU awk,这适用于 OP 提供的示例,尽管不清楚他真正想要什么
【解决方案2】:

这可能对你有用(GNU sed):

sed -n '/abc/{:a;x;z;x;:b;n;/abc/{:c;g;s/.//p;ba};/mno/d;H;$bc;bb};p' file

abcmno 循环之前或之后的任何行都将正常打印。 abc 循环和后面的abc 之间的任何行都将少打印循环的第一行和最后一行。所有其他行将被删除,即abcmno 之间的循环,之间没有abc 行。对于循环 abc 和文件末尾没有 abcmno 行的特殊情况,将打印除第一行之外的所有行。

【讨论】:

    【解决方案3】:

    这是一种适用于任何 awk 的简单方法:

    awk 'BEGIN{begpat="^abc$"; endpat="^mno$" }
         ($0 ~ endpat) { n=0; buffer=""; next }
         ($0 ~ begpat) { n=1; if(buffer) print buffer; buffer=""; next }
         (n==0) { print; next }
         {buffer = (buffer ? buffer ORS : "") $0 }
         END { if(buffer) print buffer }' file 
    

    以下逻辑表解释了其工作原理:

       from\to | begpat | endpat | END        BEGIN: BEGIN OF FILE
       --------+--------+--------+-----       END  : END OF FILE
        BEGIN  |   1    |   1    |  1
       --------+--------+--------+-----       1: print lines between [from,to]
        begpat |   1    |   0    |  1         0: don't print lines between [from,to]
       --------+--------+--------+-----
        endpat |   1    |   1    |  1
    

    以上说明只有遇到begpat时才会出现异常。只有在这种情况下,我们才建立一个缓冲区来决定是否必须打印。

    【讨论】:

      猜你喜欢
      • 2017-08-29
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-28
      • 2020-01-24
      • 2014-09-07
      相关资源
      最近更新 更多