删除包含其他图案的多线图案

时间:2014-01-15 12:03:14

标签: sed awk grep

我想删除包含另一个指定模式的模式的所有实例(方便地在新行上):

MID:

示例输入:

header
BEGIN:
1abc
7wurw
END:
BEGIN:
22xyz
MID:
34utov
END:

期望的输出:

header
BEGIN:
1abc
7wurw
END:

我正在寻找可能的一个衬垫。任何帮助将不胜感激。

7 个答案:

答案 0 :(得分:4)

使用GNU sed

sed -e :a -e '/^BEGIN:/,/^END:/ { /END:/!{$!{N;ba};};/MID:/d;}' inputfile

对于您的输入,它会返回:

header
BEGIN:
1abc
7wurw
END:

答案 1 :(得分:2)

我会使用RS, ORS变量。这里是单行:

awk -v RS="BEGIN:\n" -v ORS="" '/MID/{next}NR>1{printf RS}7' file

使用您的文件进行测试:

kent$  cat f
header
BEGIN:
1abc
7wurw
END:
BEGIN:
22xyz
MID:
34utov
END:

kent$  awk -v RS="BEGIN:\n" -v ORS="" '/MID/{next}NR>1{printf RS}7' f
header
BEGIN:
1abc
7wurw
END:

请注意,printf RS不是很好,我用它是因为我知道它是BEGIN:良好做法printf "%s", RS

答案 2 :(得分:2)

这对我来说对样本有用:

sed '/BEGIN:/,/END:/{/BEGIN/{h;d};H;/END:/!d;x;/MID:/d}' input.txt

我很确定它可以简化很多。

答案 3 :(得分:1)

BEGIN { in_block = 0; }
/BEGIN:/ { in_block = 1; lineno = 0; arr[lineno] = $0; must_write = 1; next; }
/END:/ { in_block = 0; 
         if (must_write == 1) {
              for (i = 0; i <= lineno; ++i) print arr[i]; print; 
         }
         next;
}
/MID:/ { must_write = 0; next; }
in_block == 1 && must_write == 1 { lineno++; arr[lineno] = $0; next; }
in_block == 0 { print }

这应该有效(使用提供的测试用例)。一些awk-wizards可能会找到更密集的解决方案。但是你也可以将这种处理用于其他任务。

答案 4 :(得分:1)

这可能适合你(GNU sed):

sed '/^BEGIN:/{:a;$!{N;/END:/!ba};/MID:/d}' file

答案 5 :(得分:0)

gnu awk除以END:之类的部分,因此不适用于BEGIN: - END:,但有效:

awk '!/MID:/{printf "%s%s\n",$0,RT}' RS="END:" t
header
BEGIN:
1abc
7wurw
END:

答案 6 :(得分:0)

sed -n '/BEGIN:/,/END:/ {
   H
   /END:/ {
      s/.*//
      x
      /\nMID:/ !p
      }
   }' YourFile

对于OneLiner

sed -n '/BEGIN:/,/END:/{H;/END/{s/.*//;x;/\nMID:/ !p;};}' YourFile

不适用于最后一个; (我必须在我的AIX上保留一个“\ n”)(应该在GNU上运行)

#for AIX
sed -n '/BEGIN:/,/END:/{H;/END/{s/.*//;x;/\nMID:/ !p;}
}' YourFile